134

I have the activity:

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!!!
    }
  }
}

How do I check which button has been clicked?

Dharman
  • 30,962
  • 25
  • 85
  • 135
xpepermint
  • 35,055
  • 30
  • 109
  • 163
  • 1
    [Comparison of five different ways](http://stackoverflow.com/a/27729687/3681880) to add OnClickListeners for multiple buttons – Suragch May 13 '15 at 01:32

11 Answers11

198

You will learn the way to do it, in an easy way, is:

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
    }
  };
}

Or, if you are working with just one clicklistener, you can do:

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;
      }
  }
}

Though, I don't recommend doing it that way since you will have to add an if for each button you use. That's hard to maintain.

Cristian
  • 198,401
  • 62
  • 356
  • 264
  • 1
    Well, actually that's not correct. `View` is not a `Button`, but `Button` is a `View`. Though, you can cast a `View` to a `Button`. Keep in mind that the second way to do it is not recommended... maybe that v may not be a Button, which will generate a cast exception. – Cristian Jul 23 '10 at 17:07
  • 2
    Actually both ways are not recommended, see my answer – ognian Jul 23 '10 at 17:44
  • Its actually quite simple to replace the if, elses with a single switch case statement that you switch on the id of the view and the cases are id's from R.java – slayton Sep 22 '11 at 17:18
  • Just wondering why you cast v to a Button anyway. getId() is defined for Views as well. Therefore I really wouldn't recommend the 2nd method but prefer Christian's solution! – nuala Apr 03 '12 at 10:21
77

Or you can try the same but without listeners. On your button XML definition:

android:onClick="ButtonOnClick"

And in your code define the method ButtonOnClick:

public void ButtonOnClick(View v) {
    switch (v.getId()) {
      case R.id.button1:
        doSomething1();
        break;
      case R.id.button2:
        doSomething2();
        break;
      }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Chronos
  • 1,972
  • 17
  • 22
  • 3
    Much cleaner than the other answers that use a bunch of event handlers, `if` statements, and listeners. Listeners are great if buttons are created at runtime, but that's often not the case. – Dennis Oct 15 '12 at 07:51
  • 6
    While an interesting different approach, XML hooks for listeners are rough around the corners with `Fragment`s, as the callback must reside in the activity (not the fragment). – donfede Dec 17 '12 at 00:31
  • My prob is doSomething2() cant be reached without throwing either an InvocationTargetException or a NullPointerException (or both). – Quasaur Mar 07 '13 at 13:54
  • 1
    Just a sidenote: the statement "without listeners" here is wrong. You're only declaring the listener in XML, that's all. – Hubert Grzeskowiak Apr 22 '16 at 22:15
42

I prefer:

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);
    ...
}

And then:

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

Switch-case is easier to maintain than if-else, and this implementation doesn't require making many class variables.

Ziem
  • 6,579
  • 8
  • 53
  • 86
Saad Farooq
  • 13,172
  • 10
  • 68
  • 94
  • This worked perfectly. You need to implement _OnClickListener-android.view.View_ and not _OnClickListener-android.content.DialogInterface_ – gkiko Mar 06 '13 at 17:17
16

Five Ways to Wire Up an Event Listener is a great article overviewing the various ways to set up a single event listener. Let me expand that here for multiple listeners.

1. Member Class

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. Interface Type

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. Anonymous Inner Class

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. Implementation in Activity

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. Attribute in View Layout for OnClick Events

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;
        }
    }
}

And in 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" />
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
12

If you don't want to save instances of the 2 button in the class code, follow this BETTER way (this is more clear and fast!!) :

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;
  }
}
lory105
  • 6,112
  • 4
  • 31
  • 40
12

Another way of doing it is a single listener from activity , like this:

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;
        }
    }
}

I Like to do it with single IF instead of switch-else, but if you prefer that, then you should do:

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

        case R.id.mybutton2:
        {
            DoSomething();
            break;
        }
    }
}
Ziem
  • 6,579
  • 8
  • 53
  • 86
ruhalde
  • 3,521
  • 3
  • 24
  • 28
9

The best way is by switch-ing between v.getId(). Having separate anonymous OnClickListener for each Button is taking up more memory. Casting View to Button is unnecessary. Using if-else when switch is possible is slower and harder to read. In Android's source you can often notice comparing the references by if-else:

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

I don't know exactly why they chose this way, but it works too.

ognian
  • 11,451
  • 4
  • 35
  • 33
  • because it is no longer possible since v14 where ids are not treated not constant – user1324936 Aug 31 '14 at 12:02
  • @ognian I followed up to here because you said the main answer uses deprecated approaches. Nowadays with Android 5.0 Lollipop released, is your answer still true, or time made it become a falacy, like the comment above suggests? I really don't know what to think, or which direction to take from here. – SebasSBM Aug 09 '15 at 03:35
7

use setTag();

like this:

@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;   
    }     
}     
David
  • 15,894
  • 22
  • 55
  • 66
user2644305
  • 71
  • 1
  • 2
  • I came here looking for a method to pass additional parameters to a handler, this is exactly what I wanted. The tag can be declared in Markup. – cessor Jan 06 '17 at 19:58
4
Button mybutton = new Button(ViewPagerSample.this);
mybutton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
            // TODO Auto-generated method stub
    }
});
Ziem
  • 6,579
  • 8
  • 53
  • 86
Tai Nguyen
  • 105
  • 1
  • 10
4

In addition to Cristian C's answer (sorry, I do not have the ability to make comments), if you make one handler for both buttons, you may directly compare v to b1 and b2, or if you want to compare by the ID, you do not need to cast v to Button (View has getId() method, too), and that way there is no worry of cast exception.

DonSteep
  • 1,075
  • 10
  • 10
1
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(this);

@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    if(v.getId() == R.id.button1){
        Toast.makeText(context, "Button 1 Click", Toast.LENGTH_LONG).show();
    }
}

Check this article for more details