99

I'm currently making a simple calculator app on Android. Im trying to set up the code so that when a number button is pressed it updates the calculator screen with that number. Currently I'm doing it like this.

    Button one = (Button) findViewById(R.id.oneButton);
    one.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            TextView output = (TextView) findViewById(R.id.output);
            output.append("1");
        }
    });

It works but I'm writing this same code for every single button on the calculator. As you can imagine it is very redundant. Is there anyway I can write this code in a more efficient way? One that involves not writing this method for every single button?

Kaushik
  • 6,150
  • 5
  • 39
  • 54
user3011685
  • 1,013
  • 1
  • 8
  • 7
  • implement the onclick listener in your class,it will override onclick method.Based on button id you can make operations – learner Sep 18 '14 at 05:55
  • Boopathi, can you explain more on how I would then code the one button? I made the button id "1" that way I can use "this" to access the number. Im not sure how I would then edit the TextView though. – user3011685 Sep 18 '14 at 06:04

12 Answers12

258

You Just Simply have to Follow these steps for making it easy...

You don't have to write new onClickListener for Every Button... Just Implement View.OnClickLister to your Activity/Fragment.. it will implement new Method called onClick() for handling onClick Events for Button,TextView` etc.

  1. Implement OnClickListener() in your Activity/Fragment
public class MainActivity extends Activity implements View.OnClickListener {

}
  1. Implement onClick() method in your Activity/Fragment
public class MainActivity extends Activity implements View.OnClickListener {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    @Override
    public void onClick(View v) {
      // default method for handling onClick Events..
    }
}
  1. Implement OnClickListener() For Buttons
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    setContentView(R.layout.your_layout);
    
    Button one = (Button) findViewById(R.id.oneButton);
    one.setOnClickListener(this); // calling onClick() method
    Button two = (Button) findViewById(R.id.twoButton);
    two.setOnClickListener(this);
    Button three = (Button) findViewById(R.id.threeButton);
    three.setOnClickListener(this);
}
  1. Find Buttons By Id and Implement Your Code..
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.oneButton:
            // do your code
            break;
        case R.id.twoButton:
            // do your code
            break;
        case R.id.threeButton:
            // do your code
            break;
        default:
            break;
    }
}

Please refer to this link for more information :

This will make it easier to handle many buttons click events and makes it looks simple to manage it...

Pragnesh Ghoda シ
  • 8,318
  • 3
  • 25
  • 40
  • Point 4: I am getting error on @Override tag which warns me that method does not override its method from superclass. – KasparTr Feb 23 '16 at 12:59
  • @user2984127 try implementing View.OnClickListener. – Pragnesh Ghoda シ Mar 02 '16 at 10:43
  • I used this method many times while using Eclipse, but now I switched to Android Studio and I get an error "Resource IDs cannot be used in a switch statement in Android library modules.". As of SDK tools R14 the Resource IDs are not final. The recommended fix is to replace the switch with if/else statements. – Scorpio Mar 11 '16 at 08:53
  • @Scorpio : I am using android studio too. But I never got that error. Please check that you are using proper methods and with using `view.getId()`, you are getting ID of clicked button. This is an example, you have make some changes depends on your need. Cheers. :) – Pragnesh Ghoda シ Apr 08 '16 at 06:01
  • is there any way to avoid the setting on onClickListener on each button?? I mean, if I have a large no. of buttons from which I need to listen the click events, then the code looks dirty and its tedious to write listener for each button like :button1.setOnClickListener(this);button2.setOnClickListener(this);.... buttonN.setOnClickListener(this); I there any way to avoid this?? android:onClick attribute in the layout will solve this purpose but I want something in Java source code. – srv_sud Apr 11 '16 at 18:01
  • @Scorpio is correct in case your listener is part of a library (not in case of an app). Then you can't use the id's in a switch case since they're not final (and so, not a constant) anymore since API 14. You have to use the (more ugly) if-else if construction. A pity... – GeertVc Oct 31 '17 at 06:53
  • @PragneshGhodaシ How we can do this in RecyclerView? – Ahmet Yılmaz Jul 09 '19 at 15:08
  • @AhmetYılmaz In that case you need to create listener and implement onClick in the ViewHolder. Please follow this link for more info : https://androidacademic.blogspot.com/2016/12/recyclerview-item-onclicklistener.html – Pragnesh Ghoda シ Jul 10 '19 at 08:54
  • 1
    @PragneshGhodaシ thanks for answer. I solved it after I asked in stackOverflow. https://stackoverflow.com/questions/56965159/how-can-add-same-onclick-for-all-imageview-in-recyclerview/56965409?noredirect=1#comment100470609_56965409 – Ahmet Yılmaz Jul 10 '19 at 09:29
59

You could set the property:

android:onClick="buttonClicked"

in the xml file for each of those buttons, and use this in the java code:

public void buttonClicked(View view) {

    if (view.getId() == R.id.button1) {
        // button1 action
    } else if (view.getId() == R.id.button2) {
        //button2 action
    } else if (view.getId() == R.id.button3) {
        //button3 action
    }

}
Andro
  • 952
  • 9
  • 19
11

Set a Tag on each button to whatever you want to work with, in this case probably an Integer. Then you need only one OnClickListener for all of your buttons:

Button one = (Button) findViewById(R.id.oneButton);
Button two = (Button) findViewById(R.id.twoButton);
one.setTag(new Integer(1));
two.setTag(new Integer(2));

OnClickListener onClickListener = new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        TextView output = (TextView) findViewById(R.id.output);
        output.append(v.getTag());
    }
}

one.setOnClickListener(onClickListener);
two.setOnClickListener(onClickListener);
9

I created dedicated class that implements View.OnClickListener.

public class ButtonClickListener implements View.OnClickListener {

    @Override
    public void onClick(View v) {
        Toast.makeText(MainActivity.this, "Button Clicked", Toast.LENGTH_SHORT).show();
    }

}

Then, I created an instance of this class in MainActivity

private ButtonClickListener onClickBtnListener = new ButtonClickListener();

and then set onClickListener for button

btn.setOnClickListener(onClickBtnListener);
Vadim Novitskiy
  • 179
  • 2
  • 11
  • that work, but if you use more than one button you will call always the same Listener, you should add a switch case in your method onClick with the id of each button. – lebarillier Dec 05 '18 at 05:37
  • I'm assuming if you create a class instance per button that would also alleviate this concern – Matt Strom Apr 26 '20 at 22:16
3
public class MainActivity extends AppCompatActivity implements OnClickListener  {
    Button  b1,b2;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        b1= (Button) findViewById(R.id.button);
        b2= (Button) findViewById(R.id.button2);
        b1.setOnClickListener(this);
        b2.setOnClickListener(this);
    }


    @Override
    public void onClick(View v)
    {
        if(v.getId()==R.id.button)
        {
            Intent intent=new Intent(getApplicationContext(),SignIn.class);
            startActivity(intent);
        }
        else if (v.getId()==R.id.button2)
        {
            Intent in=new Intent(getApplicationContext(),SignUpactivity.class);
            startActivity(in);
        }
    }
}
KarelG
  • 5,176
  • 4
  • 33
  • 49
2

I had a similar issue and what I did is: Create a array of Buttons

Button buttons[] = new Button[10];

Then to implement on click listener and reference xml id's I used a loop like this

for (int i = 0; i < 10; i++) {      
String buttonID = "button" + i;
        int resID = getResources().getIdentifier(buttonID, "id",
                "your package name here");
        buttons[i] = (Button) findViewById(resID);
        buttons[i].setOnClickListener(this);
    }

But calling them up remains same as in Prag's answer point 4. PS- If anybody has a better method to call up all the button's onClick, please do comment.

1

You can use this

    TextView output = (TextView) findViewById(R.id.output);
    one.setOnClickListener(youractivity.this);
    // set the onclicklistener for other buttons also

    @Override
    public void onClick(View v) {
      int id = v.getId();
    switch(id) {
    case R.id.oneButton:      
       append("1",output);
       break;
    case R.id.twoButton:
        append("2",output);
       break;
    case R.id.threeButton:
        append("3",output);
       break;
     } 
      }

 private void append(String s,TextView t){
  t.setText(s); 
}

you can identify the views in your activity in a separate method.

Gourav
  • 2,746
  • 5
  • 28
  • 45
1

Implement onClick() method in your Activity/Fragment public class MainActivity extends Activity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onClick(View v) {
 switch (itemId) {

// if you call the fragment with nevigation bar then used.

           case R.id.nav_menu1:
                fragment = new IntroductionFragment();
                break;

// if call activity with nevigation bar then used.

            case R.id.nav_menu6:
                Intent i = new Intent(MainActivity.this, YoutubeActivity.class);
                startActivity(i);
      // default method for handling onClick Events..
    }
}
Nathan
  • 65
  • 1
  • 4
  • 14
Vicky Mahale
  • 1,209
  • 11
  • 18
1
public void onClick(View v) {
    int id = v.getId();
    switch (id){
        case R.id.button1:
            //do ur code
            Toast.makeText(this,"This is button 1",Toast.LENGTH_SHORT).show();
            break;
        case R.id.button2:
            Intent intent = new Intent(this,SecondActivity.class);
            Intent.putExtra("key",value);
            startActivity(intent);
            break;
        case R.id.button3:
            //do ur code
            break;
        case R.id.button4:
            //do ur code;
            break;
        default:
            //do ur code;
    }
}
0

I find that using a long if/else chain (or switch), in addition to the list of findViewById(btn).setOnClickListener(this) is ugly. how about creating new View.OnlickListeners with override, in-line:

findViewById(R.id.signInButton).setOnClickListener(new View.OnClickListener()
    { @Override public void onClick(View v) { signIn(); }});
findViewById(R.id.signOutButton).setOnClickListener(new View.OnClickListener()
    { @Override public void onClick(View v) { signOut(); }});
findViewById(R.id.keyTestButton).setOnClickListener(new View.OnClickListener()
    { @Override public void onClick(View v) { decryptThisTest(); }});
findViewById(R.id.getBkTicksButton).setOnClickListener(new View.OnClickListener()
    { @Override public void onClick(View v) { getBookTickers(); }});
findViewById(R.id.getBalsButton).setOnClickListener(new View.OnClickListener()
    { @Override public void onClick(View v) { getBalances(); }});
mholberger
  • 337
  • 3
  • 14
0

No need of if else's or switch, Let's start: In your every Button or whatever it is (I am using ImageView), Add this attribute android:onClick="DoSomeThing"

In your Activity:

public void DoSomeThing(View v){
    ImageView img1= (ImageView) v; //you have to cast the view i.e. if it's button, it must be cast to Button like below line

    Button b1= (Button) v;

    img1.setImageBitmap(imageBitmap); //or anything you want to do with your view, This will work for all

    b1.setText("Some Text");
}

In this way, no need to find views by id, no click listeners, no redundant code, simple as above!

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Zubair Younas
  • 71
  • 1
  • 13
0

I needed one function for multiple buttons using view binding, not findViewById.

1- In the code below each button's setOnClickListener calls the same function btnTapped which has a parameter that takes in a view.

2- btnTapped runs a switch statement on the view parameter and Toasts whichever button was tapped.

3- When each button's setOnClickListener is set, I pass in it which is the view/button itself

Sample calculator with buttons 7,8,9

private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    setOnClickListeners()
}

private fun setOnClickListeners() {

    // "it" is the view/button itself
    binding.btnSeven.setOnClickListener { btnTapped(it) }
    binding.btnEight.setOnClickListener { btnTapped(it) }
    binding.btnNine.setOnClickListener { btnTapped(it) }
}

private fun btnTapped(view: View) {

    // run a switch statement to do something when each button is pressed
    when (view) {
        binding.btnSeven -> showToast("7 tapped")
        binding.btnEight -> showToast("8 tapped")
        binding.btnNine -> showToast("9 tapped")
        else -> showToast("something else tapped")
    }
}

private fun showToast(text: String) {
    Toast.makeText(this, text, Toast.LENGTH_LONG).show()
}
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256