Java - Efficient method with multiple onClickListener - java

My app currently has 5 buttons (I'm going to add more later) and when each button is clicked, it'll assign a number to an item.
I'm wondering if there's a more efficient way of writing the setOnClickListner (it seems like I have to use that since I'm using this as a fragment. I found a way to do it if I was to assign an onClick in the xml but I can't apply that to this part of the code). I have it written out 5 times (and in the future it'll be more)
buttons[0] = (Button) view.findViewById(R.id.cut1Btn);
buttons[1] = (Button) view.findViewById(R.id.cut2Btn);
buttons[2] = (Button) view.findViewById(R.id.cut3Btn);
buttons[3] = (Button) view.findViewById(R.id.cut4Btn);
buttons[4] = (Button) view.findViewById(R.id.cut5Btn);
buttons[0].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "TESTING BUTTON CLICK 1",Toast.LENGTH_SHORT).show();
data = 1;
}
});
buttons[1].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "TESTING BUTTON CLICK 2",Toast.LENGTH_SHORT).show();
data = 2;
}
});
buttons[2].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "TESTING BUTTON CLICK 3",Toast.LENGTH_SHORT).show();
data = 3;
}
});
buttons[3].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "TESTING BUTTON CLICK 4",Toast.LENGTH_SHORT).show();
data = 4;
}
});
buttons[4].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getActivity(), "TESTING BUTTON CLICK 5",Toast.LENGTH_SHORT).show();
data = 5;
}
});
Could I maybe do a switch or a loop? Like assign i = 0, i < 5, i++ for the button array and then for data make that data = i + 1 ? If so, any suggestions on how I can do that?
Thanks!

THe other answers here will work, but either use the tag (generally a bad idea and prevents any other use) and aren't really object oriented. Instead you should make a class an instantiate it.
private class MyClickListener {
private int data;
public MyClickListener(int data) {
this.data = data;
}
public void onClick(View view) {
Toast.makeText(getActivity(), "TESTING BUTTON CLICK" + data,Toast.LENGTH_SHORT).show();
}
}
...
int i=0;
for(Button button : buttons) {
button.setOnClickListener(new MyClickListener(i++));
}

You could use a common method and then implement a switch case based upon R.id of your button
An example would in like this.
in onCreate(--) method
cut1Btn = (Button) view.findViewById(R.id.cut1Btn);
cut2Btn = (Button) view.findViewById(R.id.cut2Btn);
cut3Btn = (Button) view.findViewById(R.id.cut3Btn);
cut4Btn = (Button) view.findViewById(R.id.cut4Btn);
cut5Btn = (Button) view.findViewById(R.id.cut5Btn);
cut1Btn.setOnClickListener(this);
cut2Btn.setOnClickListener(this);
cut3Btn.setOnClickListener(this);
cut4Btn.setOnClickListener(this);
cut5Btn.setOnClickListener(this);
Implement View.onClickListener in your activity and override this method in your activity
public void onClick(View v){
switch(v.getId()){
case R.id.cut1Btn:
//Put Your Code Here
break;
case R.id.cut2Btn:
//Put Your Code Here
break;
case R.id.cut3Btn:
//Put Your Code Here
break;
case R.id.cut4Btn:
//Put Your Code Here
break;
case R.id.cut5Btn:
//Put Your Code Here
break;
}
}

You can implement a switch to do this things:
Your class must implement OnClickListener and override function OnClick(View view).
Then just set OnClickListener(this) like this on onCreate method
buttons[1].setOnClickListener(this)
buttons[2].setOnClickListener(this)
buttons[3].setOnClickListener(this)
do a switch-case on override function
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
// button 1 do
break;
case R.id.button2:
// button 2 do
break;
case R.id.button3:
// button 3 do
break;
}
}

Related

Buttons outside the onCreate

Always in my apps I added buttons in void onCreate, but now I'm trying to do app with more buttons (about 10). I would like to all buttons active on start app.
In my opinion it is too much buttons to add in this onCreate and app will be starting to long.
I tried to put this:
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
})
out of onCreate
but AndroidStudio underlines setOnClickListener and view
I don't have ideas, how and where can i add button out of onCreate.
If you don't want to overcrowd your oncreate method, then create a clicklistener outside onCreate anywhere in activity and in onCreate just set it.
onCreate :
edit_a_member = (Button) findViewById(R.id.edit_member);
delete_a_member = (Button) findViewById(R.id.delete_member);
edit_a_member.setOnClickListener(handleClick);
delete_a_member.setOnClickListener(handleClick);
clickListener:
private View.OnClickListener handleClick = new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.edit_member:
member_selected = EDIT_MEMBER_SELECTED;
callDialog();
break;
case R.id.delete_member:
callDeleteAlert();
break;
}
}
};
You can simply add a separate method for your buttons in the same class, e.g.:
public void onCreate(...){
//Standard setup of views or whatever you want to do here
this.addButtons();
}
private void addButtons(){
Button b1 = new Button("Hi");
b1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
});
Button b2 = new Button("Hi to you too");
b2.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
});
}
This is an example. You can do this in soooo many ways. I feel like you should thoroughly learn Java's fundamental Object Oriented programming, because that's really what your question suggests you don't understand. Go follow a youtube tutorial. I always like "The New Boston"'s Java tutorial series on youtube.
PS: You can make code like this beautiful under the 'Words of wisdom': Don't repeat yourself
If you have to do a lot of work in your onCreate but you are worried that the UI will take too long to load you can always post a delayed runnable to a handler so in the onCreate method put :
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//add your code here
}
},10);
what this will do is your UI will load then the code in your Runnable will be executed 10 milliseconds after your UI loads thus your app will not take too long to load the UI, even though in your case I doubt it would be necessary.
If you are declaring the buttons in xml file :
Add these properties in each button Declaration in your Xml :
android:clickable="true"
android:onClick="onClick"
And now in Activity Class create a method like this :
public void onClick(View v){
switch(v.getId){
case R.id.{buttons_id_in_xml}
(Your Code)
break;
(Like for others)
}
}
If you want to add buttons dynamically :
Create a method to add the button like this:
void addButton(String buttonName, int button id){
Button button = new Button(this);
button.setText("Push Me");
(add it to parent Layout of xml)
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(id){
case id1:
(handle )
break;
(like for others)
}
}
});
}
The best way to do this is:
add implements View.OnClickListener to
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
// declare variables
private Button mBtn1;
private Button mBtn2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
// make an instance to the btns
mBtn1 = findViewById(R.id.btn1);
mBtn2 = findViewById(R.id.btn2);
// set onClickListener
mBtn1.setOnClickListener(this); // with "this" you are passing the view
mBtn2.setOnClickListener(this);
}
// implement onClick
#Override
public void onClick(View view) {
// check which btn was clicked by id
switch (view.getId()) {
case R.id.btn1:
btn1Clicked();
break;
case R.id.btn2:
btn2Clicked();
break;
}
}
private void btn1Clicked() {
// your code btn1 clicked
}
private void btn2Clicked() {
// your code btn2 clicked
}
Hope this helped. Cheers!

Can a switch case do something like this?

My idea is that I have buttons on my app that leads to a single activity. I want it to have the same text template but different contents appearing when different buttons are clicked. I already have the XML file done, I got stuck on the code. I was thinking of using switch case but can it be possibly done with switch case? Or am I being too ambitious?
EDIT: Here's the code I have so far:
public class SelectKeys extends Activity {
private static final int[] buttonIDs = {R.id.cKey, R.id.cSharpKey, R.id.dKey, R.id.dSharpKey, R.id.eKey, R.id.fKey, R.id.fSharpKey, R.id.gKey, R.id.gSharpKey, R.id.aKey, R.id.aSharpKey, R.id.bKey};
private Button[] bt = new Button[buttonIDs.length];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_keys);
for (int i = 0; i < buttonIDs.length; i++) {
final int b = i;
bt[b] = (Button) findViewById(buttonIDs[i]); // Fetch the view id from array
bt[b].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//opens up new screen
Intent intent = new Intent(getApplicationContext(), ChordKeys.class);
startActivity(intent);
}
});
}
}
public final void keyButton(final View v)
{
switch(v.getId())
{
case R.id.cKey:
{
setContentView(R.layout.activity_key_c);
break;
}
case R.id.cSharpKey:
{
setContentView(R.layout.activity_csharp_dflat);
break;
}
// adding more cases later once I get this to work
}
}
}
Of course it can be done with a switch case, you just need to create a class that implements onClickListener, and link all your buttons with this listener, like this:
final Button button= (Button) findViewById(R.id.button1);
button.setOnClickListener(new MyButtonListener());
class MyButtonListener implements View.OnClickListener{
#Override
public void onClick(View v) {
int id=v.getId();
switch (id){
case R.id.button1:
button.setText("Text1");
break;
case **:
break;
default:
break;
}
To have a centralized Click handler which can be addressed in your xml layout:
Add this method to your Java code
public final void clickHandler(final View v)
{
switch(v.getId())
{
case R.id.btn1:
{
// Do something, when you click btn1
break;
}
case R.id.btn2:
{
// Do something else, when you click btn2
break;
}
// ... more cases ...
}
}
In your xml layout:
...
<Button
android:id="#+id/btn1"
...
android:onClick="clickHandler"
/>
<Button
android:id="#+id/btn2"
...
android:onClick="clickHandler"
/>
...
Note (1): This is valid not only for Buttons, but also for ImageButtons, ImageViews, TextViews, ...
Note (2): You can use it with mixed Views at the same time (i.e.: a Button, 2 TextViews and an ImageView can all address the same clikHandler() method).

How attach two Click Listener in a button in android?

I want to attach two click listener in a button and both onclicklistener should be different. Is there any way to do this.? Can't use function to call from first to second. When I use this then I got output from second one only. I want both output.
I am working on some screening task, so whenever a use click on a button it tell me that user clicked on this in Logcat and also button do its normal task.
First is :
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("First Click" , "Clicked on button 1");
}
});
Second is :
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v2) {
if (v2 instanceof Button) {
Log.i("User Clicked a checkbox with value ", " : " + ((Button) v2).getText().toString());
}
}
});
You can't do that. Setting your second OnClickListener removes the first one.
That's why the function is called setOnClickListener() instead of addOnClickListener()
As you say, you can call two functions from the onClick()
Edit:
On your edit, you say that you want to show a message when your button is clicked.
You can add the loggging functionality that you need before doing anything else on the event, simply doing
#Override
public void onClick(View v) {
// Log something
// Your functionality
}
Or you can create a class implementing View.OnClickListener
public class MyOnClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
// Log something
}
}
And then, on your Activity:
btn.setOnClickListener(new MyOnClickListener() {
#Override
public void onClick(View v) {
super.onClick(v);
// Your functionality
}
});
You can use function in OnClickListener like-
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
run1();
run2();
}
});
private void run1(){
//Your first functionality
}
private void run2(){
//Your second functionality
}
If I understood you correctly, you could do this:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dothings(); //what you are trying to achieve with this button click
showViewInLogCat(v); //to show you the view in the logcat
}
}
where showViewInLogCat() is a function that show you which view was clicked in your logcat:
public void showViewInLogCat(View view) {
if (view instanceof Button) {
Log.i("User Clicked a checkbox with value ", " : " + ((Button) view).getText().toString());
}
//and add the other if
}
You can call this function in every OnClick event on other views
Probably if you want to do something like this..!
btn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
Log.i("First Click" , "Clicked on button 1");
// add a boolean here to check if you want to do the task or not.
doTask = true;
doGeneralTask(doTask); //to show you the view in the logcat
}
}
and in doGeneralTask(doTask) do something like this.
public void doGeneralTask(boolean doTask) {
if (doTask) {
// do whatever generalized tasks you need.
}
}

How to get button for which listener's method was invoked

When I have:
OnClickListener listener = new OnClickListener() {
#Override
public void onClick(View v) {
//getSource button here --->actionButton
}
}
button1.setOnClickListener(listener);
How to get button which was clicked inside onClick method?
See the v parameter on the onClick method which represents the view that was clicked.
Then you can use v.getId() to see which view has been clicked.
#Override
public void onClick(View v) {
if(v.getId() == R.id.button1){
//button1 clicked
}
}
Just get the id
#Override
public void onClick(View v) {
//getSource button here --->actionButton
if (v.getId() == R.id.someId)
// do some stuff
}
In this case, v is the Button clicked so you can get the id of that View (Button) and compare it using == or put it in a switch statement.
You can get the id of pressed Button using getId() method.
OnClickListener listener = new OnClickListener() {
#Override
public void onClick(View v) {
Button button = (Button) findViewById(v.getId());
Toast.makeText(this, button.getText().toString()+" button is pressed", Toast.LENGTH_SHORT).show();
}
}
In xml file use android:onClick="onClick" and view.getId() will get the id of button in which it was clicked and use switch case statement to do related jobs for each button. The code will look like this:
public void onClick(View view) {
switch (view.getId()) {
case R.id.button1:
//Do something for this button
break;
case R.id.buttton2:
//DO something for this button
break;
}

Hello World Multiple Buttons Separate Actions

I'm new to android development, and haven't programmed GUI's in java yet so button work is all new to me.
I'm making a simple hello world app, has some buttons/radios/checkboxes etc. We have to figure out a way to make it nice, there is nothing specific in the brief. so I figured I'd get some buttons and show the different kinds of toast, maybe change the background etc.
so I implemented a toast based off a tutorial, but it works on all of the instantiated buttons instead of just the one I want. I would like the other button to do something else.
I think it has to do with the onClickListener, but beyond that I'm stuck.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn1 = (Button) findViewById(R.id.button1);
btn1.setOnClickListener(this);
btn2 = (Button) findViewById(R.id.button2);
btn2.setOnClickListener(this);
cb=(CheckBox)findViewById(R.id.check);
cb.setOnCheckedChangeListener(this);
browser=(WebView)findViewById(R.id.webkit);
browser.loadUrl("http://www.google.com/search");
}
public void onClick(View v) {
new AlertDialog.Builder(this).setTitle("MessageDemo").setMessage(
"This is an Alert Dialogue Toast").setNeutralButton(
"Here, here!", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
Toast.makeText(HelloWorldActivity.this,
"<clink, clink>", Toast.LENGTH_SHORT).show();
}
}).show();
}
and here's the xml for the buttons
<Button android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Testa"
android:layout_weight="0.2"></Button>
You've added the same onClickListener to each button so they will have the same behavior. You can actually create the listener right inside the setOnClickListener call, like this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn1 = (Button) findViewById(R.id.button1);
btn1.setOnClickListener( new OnClickListener() {
public void onClick(View v) {
new AlertDialog.Builder(this).setTitle("MessageDemo").setMessage(
"This is an Alert Dialogue Toast").setNeutralButton(
"Here, here!", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
Toast.makeText(HelloWorldActivity.this,
"<clink, clink>", Toast.LENGTH_SHORT).show();
}
}).show();
}
});
btn2 = (Button) findViewById(R.id.button2);
btn2.setOnClickListener( new OnClickListener() {
public void onClick(View v) {
// Do something different here.
}
});
// The rest of onCreate
}
EDIT: I've updated the answer to make it clear which parts of your original code would go where, but I usually wouldn't stick a big chunk of code like that inside of the onClick as it's not very readable. I'd prefer something more like this:
public void onCreate(Bundle savedInstanceState) {
// other onCreate code
btn1 = (Button) findViewById(R.id.button1);
btn1.setOnClickListener( new OnClickListener() {
public void onClick(View v) {
showBtn1ClickedDialog();
}
});
// other onCreate code
}
private void showBtn1ClickedDialog() {
new AlertDialog.Builder(this).setTitle("MessageDemo").setMessage(
"This is an Alert Dialogue Toast").setNeutralButton(
"Here, here!", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dlg, int sumthin) {
Toast.makeText(HelloWorldActivity.this,"<clink, clink>", Toast.LENGTH_SHORT).show();
}
}).show();
}
In addition to goto10's solution, if you're not interested in defining the listeners in-line, your existing click handler can check the ID of the view:
public void onClick(View view) {
switch (view.getId()) {
case R.id.about_button:
// handle about
break;
// etc.
I tend towards goto10's solution, or even inner classes, rather than a switch statement like this, but it's another option. That said, I'm voting up his/her answer, and not mine.
One reason to use a switch instead of inner classes is memory usage, although with modern devices, this might not be a huge issue--but each inner class does take more space, and if the handler is small, IMO is more efficient to do it this way.
Clicking on any button generates an event which is caught by the onClick eventListener. But it doesn't automatically distinguish between the events as to which click generated the event. The information is contained in the View v and by using a switch case on the view, we can have separate events for different clicks.
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.btn1:
//Do something here
break;
case R.id.btn2:
//Do something else here
break;
case R.id.btn3:
break;
}
}
A summary of how you can use Listeners in your application.

Categories

Resources