複数のLayout
sで構成されるButton
がXMLで定義されています。
現在、ボタンに対してイベントハンドラを定義するためにOnCreate
メソッドでこれを行っています。
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button newPicButton = (Button)findViewById(R.id.new_button);
newPicButton.setOnClickListener(btnListener);
..... similarly for other buttons too
.....
}
Button
のonClick
イベント内で、カメラIntent
を起動して写真を取得し、onActivityResult
コールバック内で、イベントハンドラーを再度設定します。 View
を次のように設定します。
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
setContentView(R.layout.main);
Button newPicButton = (Button)findViewById(R.id.new_button);
newPicButton.setOnClickListener(btnListener);
...similarly for other buttons too
}
私はAndroidに不慣れで、毎回イベントを再定義するこのアプローチは非常に汚いようです。このようなシナリオでボタンイベントハンドラーを定義する上でのベストプラクティスは何かを知りたいです。 。
編集:クラス全体を貼り付ける
public class CameraAppActivity extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button newPicButton = (Button)findViewById(R.id.new_button);
newPicButton.setOnClickListener(btnListener);
}
//---create an anonymous class to act as a button click listener---
private OnClickListener btnListener = new OnClickListener()
{
public void onClick(View v)
{
//Intent newPicIntent = new Intent(v.getContext(), NewPictureActivity.class);
//startActivityForResult(newPicIntent, 0);
Intent cameraIntent = new Intent(Android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, 999);
}
};
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
setContentView(R.layout.main);
Button newPicButton = (Button)findViewById(R.id.new_button);
newPicButton.setOnClickListener(btnListener);
//if I comment last two lines nothing happens when I click on button
}
主な質問は
setContentView(R.layout.main);
Button newPicButton = (Button)findViewById(R.id.new_button);
newPicButton.setOnClickListener(btnListener);
onActivityResult
内でイベントを再登録します。正しいアプローチですか?それとも私は何か間違ったことをしていますか?イベントを再登録しないと、ボタンをクリックしても何も起こらないからです。
XMLレイアウトでonClickイベントを登録してから、コードで処理してみませんか。これは私がそれをする方法です:
<Button
Android:id="@+id/my_btn"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="Click me"
Android:onClick="onBtnClicked">
</Button>
次に、クリックを処理するメソッドを作成します
public void onBtnClicked(View v){
if(v.getId() == R.id.my_btn){
//handle the click here
}
}
または、コード内のアイテムごとにOnClickListenerを個別に設定できます。次に、if/elseまたはswitchステートメントを使用して、Originを決定します。
これにより、1つのレイアウトからすべてのボタンを処理する1つのメソッドを作成できます。
更新:
これは有効なアプローチですが、2番目のオプションを強くお勧めします。特にフラグメントを操作する場合は、よりクリーンで保守が容易です。
コードを使用した最適なアプローチを次に示します。
public class MyTest extends Activity implements OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//... some other code here to init the layout
Button btn1 = (Button)findViewById(R.id.button1);
Button btn2 = (Button)findViewById(R.id.button2);
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.button1:
break;
case R.id.button2:
break;
}
}
}
インターフェースを備えた新しいクラスは、実装を分離したい場合(他の場所で同じクラスコードを使用する場合、別の別のクラスファイルに移動する場合など)にのみ有効ですが、一般的には現在のアクティビティとonClickの実装は、そこで定義されているオブジェクトを参照して実行されることに依存しているため、私が提案するメソッドを必ず使用する必要があります。
クラスインターフェイスの作成は、別々のクラスまたはアクティビティ間の通信を実現し、物事を区別したい場合にのみ有効です。それ以外は、このためのサブクラスを作成するのは悪い習慣です。
これが最良のアプローチです
@Override
public void onCreate(Bundle savedInstanceState) {
button1.setOnClickListener(onClickListener);
button2.setOnClickListener(onClickListener);
button3.setOnClickListener(onClickListener);
}
private OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(final View v) {
switch(v.getId()){
case R.id.button1:
//DO something
break;
case R.id.button2:
//DO something
break;
case R.id.button3:
//DO something
break;
}
}
};
定義されたベストプラクティスはありません。ユースケースに大きく依存します。ボタンのonClick
属性を使用して、XMLレイアウトでそれらを定義できます。
XMLの例:
<!-- Stuff -->
<Button Android:id="@+id/my_button"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="Click Me!"
Android:onClick="myClickMethod" />
Javaの例:
// stuff
public void myClickMethod(View v) {
// more stuff
}
そうすれば、OnClickListener
を自分で実装する必要はありません。各ボタンに同じonClick
メソッドを割り当ててから、ビューごとにトリガーするアクションを決定するか、ボタンごとに個別のメソッドを設定できます。
一般に、複数のボタンに1つのOnClickListener
を使用することはお勧めしません。わかりやすい名前を使用すると、各リスナーが何をすべきかを理解しやすくなります。
Butter Knife :を使用することで、「現代の」DIの方法が好きです。
@InjectView(R.id.buttonAlert)
Button buttonAlert;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
}
@OnClick(R.id.buttonAlert)
public void alertClicked(View v){
// your logic
}
@Hasanこれは私が見つけた最高のアプローチであり、毎回完璧に機能します。
Layout.xmlで、ボタンのonClickを定義します
<Button Android:id="@+id/Button01"
Android:onClick="@string/method"
Android:focusable="true" Android:clickable="true"
">
</Button>
R.stringファイルに次の行を追加します
string name = "method"> buttonFunction
Sample.Javaファイルでは、ボタンをクリックするとR.stringで定義された関数が呼び出され、次のようになります。
public void buttonFunction(View view){//ボタンのクリックで好きなことをする}
ここに私がそれをした方法があります:
@オーバーライド
public void onClick(View view) {
Intent intent;
switch(view.getId()){
case R.id.home_button:
//DO something
intent = new Intent(HashTagActivity.this,MainActivity.class);
startActivity(intent);
break;
case R.id.back_button:
//DO something
intent = new Intent(HashTagActivity.this,ClassActivity.class);
startActivity(intent);
break;
case R.id.favorite_button:
//DO something
break;
case R.id.copy_button:
//DO something
break;
}
}
うまくいきます。
これは古いことは知っていますが、なぜonClickListener
からonActivityResult
を追加できないのか不思議に思っているなら、それはボタンがヌルだからです。 (onCreate
で行ったように)もう一度初期化すると、リスナーを追加できます。ただし、他のすべてもnullになるため、注意してください。たとえば、EditText
からデータを取得する場合は、それも初期化する必要があります(オブジェクトがlisneterがトリックを行います)。
アクティビティはOnClickListenerを実装し、単一のOnCLick()メソッド内ですべてのボタンのすべてのイベント処理を記述する必要があります。
問題は、ボタンonPicButtonのオブジェクトが、onCreate関数のスコープ内でのみ有効なローカルオブジェクトとして作成され、その関数が終了するとすぐに、ガベージコレクターがボタンのオブジェクトの割り当てを解除することです。あなたがする必要があるのは、メソッドの外でnewPicButtonオブジェクトを宣言し、onCreateメソッドでそれをリスナーに割り当てることです。これで問題が解決します。onActivityResultメソッドでnewPicButtonのコードを削除しても何も起こらない理由を説明できたらと思います。