Android Programming: Calling function with different input using onClick - java

I am new to android programming and so please pardon if the question looks stupid.
I am creating a Calculator in Android and for the user interface I have many buttons (around 20 for 10 digits, and various operation). Now there is a string expression that I calculate once the user presses the button "=". However if he presses any other button then the input is updated. Say he presses "1" then input =1; then he presses 2 then input becomes "12" and so on.
So I need to call the same function whenever various buttons are pressed, but the input to the function is different.
I can go-by this by making n different functions, one for each button but that is not very scalable.
So how can I go about it?
The current xml file is:
<Button
android:id="#+id/Button01"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/Button03"
android:layout_alignBottom="#+id/Button03"
android:layout_toRightOf="#+id/Button03"
android:onClick="UpdateExpression_/"
android:text="/" />
<Button
android:id="#+id/Button02"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/Button01"
android:layout_alignBottom="#+id/Button01"
android:layout_toRightOf="#+id/Button01"
android:onClick="UpdateExpression_X"
android:text="x" />
I need to update to android:onClick="UpdateExpression" and mention some input to this function call.
Thank you.

You will need a central onClick method, let's call it updateExpression(View v) Also a note about your code: method names should start with a lowercase letter, it's a Java naming convention.
android:onClick="updateExpression"
Now the implementation:
public void updateExpression (View v)
{
switch (v.getId())
{
case R.id.button1:
//do stuff here
break;
case R.id.button2:
//do other stuff here
break;
}
}
The reason you need v.getId() is because you're checking the id of the button then doing something if it's that particular id. This logic is needed since all your buttons will implement that same method.

Here is the implementation using code....
In the onClick function, compare the v.getId() to each of your Android layout ids, like R.id.button1 R.id.button2 etc...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Here are some buttons defined in the XML layout as button1, button2, etc...
Button button1 = (Button)findViewById(R.id.button1);
button1.setOnClickListener(myListener);
Button button2 = (Button)findViewById(R.id.button2);
button2.setOnClickListener(myListener);
Button button3 = (Button)findViewById(R.id.button3);
button3.setOnClickListener(myListener);
}
//Create an anonymous implementation of OnClickListener
private OnClickListener myListener = new OnClickListener() {
public void onClick(View v) {
Log.d(logtag,"onClick() called");
Toast.makeText(MainActivity.this, "The " + v.getId() + " button was clicked.", Toast.LENGTH_SHORT).show();
}
};

Related

Is there a Java command that means "if any button is pressed"?

I'm trying to work on some code I did for a dice rolling app, where if the roll button was pressed it would display random dice sides.
I am trying to re-use this concept for my multiple choice quiz app, where if any button is pressed, right, or wrong, it will move on to the next question:
I was thinking it would look something like this, with "button" representing all buttons being pressed.
However in this multiple choice quiz there will only be 4 buttons (A, B, C and D) that I want to have cause this happen if pressed. I'm sure I could make this happen by repeating the paragraph of code 4 times with each button, but I was wondering if there was a simpler way to have all 4 buttons be represented on the same line
(A lot of the code I'm showing is meant to be for a dice app it's mainly the first word of the first line I want help with)
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("multic", "the Button has been pressed!");
Random randomNumberGenerator = new Random();
int number = randomNumberGenerator.nextInt(8);
Log.d("Dicee", "the random number is: " + number);
leftDice.setImageResource(diceArray[number]);
int number1 = randomNumberGenerator.nextInt(8);
rightDice.setImageResource(diceArray[number1]);
}
});
I expect that after one of the buttons is pressed it will move on to the next question.
You can define the listener like this:
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("multic", "the Button has been pressed!");
Random randomNumberGenerator = new Random();
int number = randomNumberGenerator.nextInt(8);
Log.d("Dicee", "the random number is: " + number);
leftDice.setImageResource(diceArray[number]);
int number1 = randomNumberGenerator.nextInt(8);
rightDice.setImageResource(diceArray[number1]);
}
};
and then set it to as many buttons as you want:
button1.setOnClickListener(listener);
button2.setOnClickListener(listener);
button3.setOnClickListener(listener);
button4.setOnClickListener(listener);
You can use a single listener object with a switch statement to check which button is clicked.
Button b1,b2;
//findViews
View.OnClickListener listener=new View.OnClickListener() {
#Override
public void onClick(View v) {
//code
switch((Button)v){
case b1:
//code
break;
case b2:
//code
break;
}
//code
}
};
b1.setOnClickListener(listener);
b2.setOnClickListener(listener);
For a multiple choice quiz, with a set of 4 possible answers, I would suggest that you use a RadioGroup with constituent RadioButtom objects, like so:
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton android:id="#+id/radio_pirates"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/pirates"
android:onClick="onRadioButtonClicked"/>
<RadioButton android:id="#+id/radio_ninjas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/ninjas"
android:onClick="onRadioButtonClicked"/>
</RadioGroup>
Notice how each RadioButton has the onClick attribute. You can name the same method for all radio buttons, and then in the activity or fragment use one method for all buttons with a switch statement, like so:
public void onRadioButtonClicked(View view) {
// Is the button now checked?
boolean checked = ((RadioButton) view).isChecked();
// Check which radio button was clicked
switch(view.getId()) {
case R.id.radio_pirates:
if (checked)
// Pirates are the best
break;
case R.id.radio_ninjas:
if (checked)
// Ninjas rule
break;
}
}
To read more: https://developer.android.com/guide/topics/ui/controls/radiobutton#java
Multiple different choices as i am thinking it:
1)
Set android:onClick="onNextQuestion" on xml of all your buttons.
then in your java code write:
public void onNextQuestion(View view) {
// Do something in response to button click
}
2) (Better as can work in more cases) Make an NextQuestionClickListener class which will implement the interface View.OnClickListener and will implement the method onClick doing the code you wish.
class NextQuestionClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
// Do something in response to button click
}
}
Then set the listener to each button:
NextQuestionClickListener nextQuestionClickListener = new NextQuestionClickListener();
Button button1 = (Button) findViewById(R.id.button1);
Button button2 = (Button) findViewById(R.id.button2);
...
button1.setOnClickListener(nextQuestionClickListener);
button2.setOnClickListener(nextQuestionClickListener);
...
3) Using RxJava and RxBindings
RxView.clicks(button1)
.mergeWith(RxView.clicks(button2))
.mergeWith(RxView.clicks(button3))
.mergeWith(RxView.clicks(button4))
.subscribe(aVoid -> {
// Do something in response to button click
}, throwable -> Log.e(TAG, "error in handling click of next question", throwable));
4) Also i found butterknife where you can do:
#Onclick({R.id.button1,R.id.button2,R.id.button3,R.id.button4})
void onButtonClick(View aView) {
// Do something in response to button click
}

bind 2 buttons with equal functionality on different activities

I have a 2 diffetent activity with button. These buttons have a equal functionality and equal ids. What is the best way to create listener of these buttons? The very long "switch" or setting "OnClick" state? On the second way I may forget to change something.
The first way:
XML:
<Button
android:id="#+id/btn_main_continue"
android:text="#string/btn_main_continue" />
JAVA:
View button = findViewById(R.id.btn_main_about);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
...
}
}
});
The second way:
XML:
<Button
android:id="#+id/btn_main_continue"
android:text="#string/btn_main_continue"
android:onClick="onClickButtonAbout" />
JAVA:
public void onClickButtonAbout(View view) {
...
}
I would suggest making your activity implement an OnClickListener, then override the onClick method in there with your switch case statements inside.
This way, you just need to put eg. button.setOnClickListener(this) in your activity.
It is kind of clean and avoids overstepping.
On another note, try to keep the ids of the XML layouts unique.

Android onClickListener - Android Studio bug or my own mistake?

The previous snippet of code has been written down by the aid of random sites and answers from StackOverflow, but somehow not working. I should add that I am an absolute beginner at making apps and my experience with Java is very limited as well.
The errors is the following:
"setOnClickListener": Marked red.
"public void onClick(View v) {": Here "v" is marked red, for some
reason. It continues being red in "String text = v.toString();".
The program also finds my semicolon redundant at the end of the
snippet.
I am using the beta of Android Studio on Elementary OS, using OpenJDK.
Button button_1 = (Button) findViewById(R.id.btn_1);
button_1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String text = v.toString();
displayPassword(text);
}
});
I could have made any number of mistakes, that's for sure. But any nudge in the right direction would be very appreciated.
My suggestion is:Set the onClick in the XML file, and create the method in the current class.
<Button
android:id="#+id/btn_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="click" />
public void click(View arg0) {
}
Agree with Graph that you should have to #Override the onClick method. Not sure what's wrong with it there. In fact, when I typed your example into Android Studio, I got 3 letters into OnClickListener and it automatically filled in the rest, including the #Override.
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String text = v.toString();
// do something with the text.
}
});
Also, I don't think v.toString() is going to get you any useful information. If you want the text off the button, you're going to want to cast it to a button then call getText():
Button button = (Button) v;
String text = button.getText().toString();
or, you could do:
String text = ((Button)v).getText().toString();
Simply calling v.toString() is going to get you a description of that button, not the text on it.
I believe you need to #Override the onClick method.
Button button_1 = (Button) findViewById(R.id.btn_1);
button_1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String text = v.toString();
displayPassword(text);
}
});
Just press " ctrl+shift+o " and add 1 library which you shows on screen prob solved

Ignore EditText setOnClickListener code to be able to edit text

I have an EditText as a text field to accept a telephone number amongst other personal details on an activity.
On activity launch the EditText is disabled until the user selects edit to edit the information. It is then enabled and allows the user to type a number in it.
Once the user clicks to save the data the EditText is made unfocusable using
txtPhone.setFocusable(false);
It then uses an onClickListener to allow the user to click it and call the number it contains.
When the user clicks edit to edit the number, I am setting
txtPhone.setFocusable(true);
To allow the EditText to receive focus however it is still seems to be using the onClickListener and won't allow the text to be edited giving the warning in log cat:
TextView does not support text selection. Action mode canceled.
Code for the EditText listener:
txtPhone.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(txtPhone.isFocusable()==false)
{
if(txtPhone.getText().length() > 1)
{
// Call number
// Using Toast to show listeners working first
Toast.makeText(getApplicationContext(), "Calling... " + txtPhone.getText().toString(), Toast.LENGTH_LONG).show();
}
}
}
});
The EditText xml:
<EditText
android:id="#+id/txtPhone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:enabled="false"
android:hint="Telephone..."
android:inputType="phone"
android:maxLength="11" />
How can I make it so that the text is editable like on first launch and ignore the listener but when not focusable call the number, I don't seem to be able to get it to work as desired
I wasn't able to reproduce the warning you were getting, but wasn't able to get the Toast to appear on pressing the textbox when not focused. I did try the following to replicate what you're trying to achieve. Hopefully I understood you correctly.
EditText
Instead of using enabled="false" I used focusable="false". This will have a similar behaviour to enabled being false, but allows the onClickListener of txtPhone to fire.
<EditText
android:id="#+id/txtPhone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:focusable="false"
android:hint="Telephone..."
android:inputType="phone"
android:maxLength="11" />
Listeners
Since you didn't show code for the buttons, I used a button called btnEdit to switch between focuses. Instead of txtPhone.setFocusable(true); I used txtPhone.setFocusableInTouchMode(true); to properly get the edit text to be editable.
btnEdit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (txtPhone.isFocusable()) {
txtPhone.setFocusable(false);
} else {
txtPhone.setFocusableInTouchMode(true);
}
}
});
txtPhone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (txtPhone.isFocusable() == false) {
if (txtPhone.getText().length() > 1) {
// Call number
// Using Toast to show listeners working first
Toast.makeText(MainActivity.this, "Calling... " + txtPhone.getText().toString(), Toast.LENGTH_LONG).show();
}
}
}
});
So when I first start the activity, txtPhone is not editable. When I click the edit button, txtPhone becomes editable and I am able to enter numbers. Lastly, I click the edit button again to disable txtPhone and when I press on it, the Toast appears.

"Catch" Multiple Buttons with One Method

Forgive me if this has been asked before. I have poured through this site and many others and can't seem to find an answer. I have a working Android app but I'm trying to clean the code up. I have 3 buttons:
public Button button1, button2, button3;
Then, I have a method that "grabs" the clicks:
public void getButtonClick(View view)
{
switch(view.getId())
{
case R.id.button1:
// Do something button1 related here
break;
case R.id.button2:
// Do something button2 related here
break;
case R.id.button3:
// Do something button3 related here
}
}
What I'd like to know is if there is any way I can have a generic method that will just wait for a button click and grab that variable so that I can avoid the multiple switch-case statements. Something on the line of:
public void oneMethodForAll(View view)
{
clkdBtn = view.getButtonThatWasClicked();
// Do stuff
}
Any help is greatly appreciated. TIA
One thing you can do is to have the activity implement View.OnClickListener:
public class FooActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle icicle) {
Button btn1 = (Button) findViewById(R.id.button1);
btn1.setOnClickListener(this);
Button btn2 = (Button) findViewById(R.id.button2);
btn2.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.button1:
// Button 1 was clicked
break;
case R.id.button2:
// Button 2 was clicked
break;
}
}
}
That will save you a little bit of typing since you're not creating a bunch of anonymous click handlers, but you will still have to set the onClickListener of each button individually.
Typically you implement different handlers for different buttons since the action the button will signal is usually different.
You can cast your View to a Button by using the View which is being passed as the sole parameter into your handler.
Button clickedButton = (Button)view;
If all you care about is the id of the button and your action will be based on that value then create separate handlers.
You can just do:
clkdBtn = (Button)view;
Usually the Button itself isn't used though. getButtonClick() should respond to the button presses with their corresponding action... I'm not sure why you'd need the actual button view itself.
If you want the text that the Button is showing, you could use:
String text = ((Button)view).getText();

Categories

Resources