Android OnClickListener-ボタンを識別する


134

私は活動しています:

public class Mtest extends Activity {
  Button b1;
  Button b2;
  public void onCreate(Bundle savedInstanceState) {
    ...
    b1 = (Button) findViewById(R.id.b1);
    b2 = (Button) findViewById(R.id.b2);
    b1.setOnClickListener(myhandler);
    b2.setOnClickListener(myhandler);
    ...
  }
  View.OnClickListener myhandler = new View.OnClickListener() {
    public void onClick(View v) {
      // MY QUESTION STARTS HERE!!!
      // IF b1 do this
      // IF b2 do this
      // MY QUESTION ENDS HERE!!!
    }
  }
}

クリックされたボタンを確認するにはどうすればよいですか?


1
複数のボタンにOnClickListenersを追加するための5つの​​異なる方法の比較
Suragch '13年

回答:


199

あなたはそれを行う方法を簡単な方法で学びます:

public class Mtest extends Activity {
  Button b1;
  Button b2;
  public void onCreate(Bundle savedInstanceState) {
    ...
    b1 = (Button) findViewById(R.id.b1);
    b2 = (Button) findViewById(R.id.b2);
    b1.setOnClickListener(myhandler1);
    b2.setOnClickListener(myhandler2);
    ...
  }
  View.OnClickListener myhandler1 = new View.OnClickListener() {
    public void onClick(View v) {
      // it was the 1st button
    }
  };
  View.OnClickListener myhandler2 = new View.OnClickListener() {
    public void onClick(View v) {
      // it was the 2nd button
    }
  };
}

または、クリックリスナーを1つだけ使用している場合は、次のようにできます。

View.OnClickListener myOnlyhandler = new View.OnClickListener() {
  public void onClick(View v) {
      switch(v.getId()) {
        case R.id.b1:
          // it was the first button
          break;
        case R.id.b2:
          // it was the second button
          break;
      }
  }
}

ただし、if使用するボタンごとにを追加する必要があるので、そのようにすることはお勧めしません。それを維持するのは難しいです。


1
まあ、実際にはそれは正しくありません。ViewないがButton、しかし、ButtonですView。けれども、あなたはキャストすることができますViewButton。それを行う2番目の方法は推奨されないことを覚えておいてください...多分そのvはボタンではなく、キャスト例外を生成するかもしれません。
クリスティアン

2
実際には両方の方法は推奨されていません。私の答えを参照してください
ognian

if、elseをビューのIDをオンにする単一のswitch caseステートメントで置き換えることは実際には非常に簡単で、ケースはR.javaのIDです
slayton

とにかくvをButtonにキャストする理由を考えているだけです。getId()はビューにも定義されています。したがって、私は実際には2番目の方法はお勧めしませんが、クリスチャンの解決策を優先します!
nuala

77

または、リスナーなしで同じことを試すことができます。ボタンのXML定義:

android:onClick="ButtonOnClick"

そしてあなたのコードでメソッドを定義しますButtonOnClick

public void ButtonOnClick(View v) {
    switch (v.getId()) {
      case R.id.button1:
        doSomething1();
        break;
      case R.id.button2:
        doSomething2();
        break;
      }
}

3
一連のイベントハンドラー、ifステートメント、およびリスナーを使用する他の回答よりもはるかにクリーンです。ボタンが実行時に作成される場合、リスナーは素晴らしいですが、それは多くの場合そうではありません。
Dennis、

6
興味深い異なるアプローチですが、Fragmentコールバックは(フラグメントではなく)アクティビティ内に存在する必要があるため、リスナーのXMLフックはsで角を曲がっています。
donfede

私の問題は、doSomething2()がInvocationTargetExceptionまたはNullPointerException(あるいはその両方)をスローせずに到達できないことです。
Quasaur 2013年

1
余談ですが、ここで「リスナーなし」という文は間違っています。リスナーをXMLで宣言するだけです。それだけです。
Hubert Grzeskowiak

42

私は好む:

class MTest extends Activity implements OnClickListener {
    public void onCreate(Bundle savedInstanceState) {
    ...
    Button b1 = (Button) findViewById(R.id.b1);
    Button b2 = (Button) findViewById(R.id.b2);
    b1.setOnClickListener(this);
    b2.setOnClickListener(this);
    ...
}

その後:

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.b1:
            ....
            break;
        case R.id.b2:
            ....
            break;
    }   
}

Switch- caseよりも保守が容易であるif- else、そしてこの実装は、多くのクラス変数を作成する必要はありません。


これは完全に機能しました。OnClickListener-android.content.DialogInterfaceではなく、OnClickListener-android.view.View
gkiko

16

イベントリスナーを接続する5つの方法は、単一のイベントリスナーを設定するさまざまな方法を概説する優れた記事です。複数のリスナーのためにここでそれを拡張してみましょう。

1.メンバークラス

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //attach an instance of HandleClick to the Button
        HandleClick handleClick = new HandleClick();
        findViewById(R.id.button1).setOnClickListener(handleClick);
        findViewById(R.id.button2).setOnClickListener(handleClick);
    }    
    private class HandleClick implements OnClickListener{
        public void onClick(View view) {
            switch(view.getId()) {
            case R.id.button1:
                // do stuff
                break;
            case R.id.button2:
                // do stuff
                break;
            }
        }
    }
}

2.インターフェイスタイプ

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.button1).setOnClickListener(handleClick);
        findViewById(R.id.button2).setOnClickListener(handleClick);
    }
    private OnClickListener handleClick = new OnClickListener() {
        public void onClick(View view) {
            switch (view.getId()) {
            case R.id.button1:
                // do stuff
                break;
            case R.id.button2:
                // do stuff
                break;
            }
        }
    };
}

3.匿名の内部クラス

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                // do stuff
            }
        });
        findViewById(R.id.button2).setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                // do stuff
            }
        });
    }
}

4.活動における実装

public class main extends Activity implements OnClickListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        findViewById(R.id.button1).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
    }
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.button1:
            // do stuff
            break;
        case R.id.button2:
            // do stuff
            break;
        }
    }
}

5. OnClickイベントのビューレイアウトの属性

public class main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    public void HandleClick(View view) {
        switch (view.getId()) {
        case R.id.button1:
            // do stuff
            break;
        case R.id.button2:
            // do stuff
            break;
        }
    }
}

そしてxmlで:

<Button
    android:id="@+id/button1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="HandleClick" />
<Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="HandleClick" />

12

2ボタンのインスタンスをクラスコードに保存したくない場合は、このより良い方法に従ってください(これはより明確で高速です!!):

public void buttonPress(View v) {
  switch (v.getId()) {
    case R.id.button_one:
        // do something
        break;
    case R.id.button_two:
        // do something else
        break;
    case R.id.button_three:
        // i'm lazy, do nothing
        break;
  }
}

12

これを行う別の方法は、次のようなactivityからの単一のリスナーです。

public class MyActivity extends Activity implements OnClickListener {
    .......  code

    //my listener
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.mybutton) { 
            DoSomething();
            return;
        }

        if (v.getId() == R.id.mybutton2) { 
            DoSomething2();
            return;
        }
    }
}

私はswitch-elseの代わりに単一のIFでそれを行うのが好きですが、それを望む場合は、次のようにする必要があります。

//my listener
@Override
public void onClick(View v) {
    switch(v.getId()) {
        case R.id.mybutton:
        { 
             DoSomething();
             break;
        }

        case R.id.mybutton2:
        {
            DoSomething();
            break;
        }
    }
}

9

最善の方法は、switchv.getId()の間に-ingすることです。ボタンごとに個別の匿名OnClickListenerを使用すると、より多くのメモリを消費します。ビューをボタンにキャストする必要はありません。切り替えが可能な場合にif-elseを使用すると、速度が遅くなり、読みにくくなります。Androidのソースでは、if-elseによる参照の比較に気付くことがよくあります。

if (b1 == v) {
 // ...
} else if (b2 == v) {

彼らがなぜこのように選んだのか正確にはわかりませんが、それもうまくいきます。


これは、IDが処理されないv14以降では不可能なためです
user1324936 '31

@ognian主な回答は非推奨のアプローチを使用しているとあなたが言ったので、私はここまでフォローしました。Android 5.0 Lollipopがリリースされた今日、あなたの答えはまだ本当ですか、それとも、上記のコメントが示唆するように、それが偽造になったのですか?どう考えたらいいのか、ここからどの方向に行けばいいのか本当にわかりません。
SebasSBM 2015

7

setTag();を使用します。

このような:

@Override    
public void onClick(View v) {     
    int tag = (Integer) v.getTag();     
    switch (tag) {     
    case 1:     
        System.out.println("button1 click");     
        break;     
    case 2:     
        System.out.println("button2 click");     
       break;   
    }     
}     

ハンドラーに追加のパラメーターを渡すメソッドを探してここに来ました。これがまさに私が欲しかったものです。タグはマークアップで宣言できます。
cessor

4

Cristian Cの回答に加えて(申し訳ありませんが、コメントを付けることができません)、両方のボタンに対して1つのハンドラーを作成する場合、vをb1およびb2と直接比較するか、IDで比較する場合は、 vをButtonにキャストする必要はありません(ビューにもgetId()メソッドがあります)。そのようにすれば、キャスト例外の心配はありません。


別のオプションは、「if(v instanceof Button){//ボタンにキャストして、ここで何かを行う}」を実行することです
Andy Zhang

4
Button mybutton = new Button(ViewPagerSample.this);
mybutton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
            // TODO Auto-generated method stub
    }
});

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.