Defining a clicked button - java

I have 9 buttons.
Each is collored to either red, blue or green.
The user has to click a green box and then the game gives him a point.
So in order to check if the box is colored green, I need to define it, get the color from it and compare it to the color the user has to pick, but I have a problem.
The problem is with defining the clicked button in order to use it to getColor()
I can make 9 functions, first defining first button, second defining second button etc.
But is there any faster way to do it?
Can I do something like
Button button = (Button)findViewById(R.id.THIS_CURRENT_BUTTON);

Yes. Because an onClick listener gets passed into it the view that was clicked, you can make just one onClick listener and assign it to all of the buttons:
View.OnClickListener listenerToCheckColor = new View.OnClickListener () {
#Override
public void onClick(View v) {
Button button = (Button)v;
if (((ColorDrawable)button.getBackground()).getColor() == yourGreenColor)
{
// + 1 point
}
}
});
You can see from this line Button b = (Button)v;, the view that was pressed is cast to a Button, leaving you with a button the same way that Button button = (Button)findViewById(R.id.THIS_CURRENT_BUTTON); would.
After creating the listener, it needs to be assigned to each button:
for(Button button : myArrayOfButtons){
button.setOnClickListener(listenerToCheckColor);
}

You can use View.setTag() or android:tag in xml. When set button green color, you set green tag by code btn.setTag("green");. If you want to know what color the button is, you can know by code below:
String tag = (String) btn.getTag();
if ("green".equals(tag)) {
//button is green
}

You don't need separate 9 functions. You can have one function to check which colored button is clicked.
XML Layout:
Add android:onClick="btnPressed" to all your buttons like below
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="btnPressed"
android:text="Button"
android:background="#color/green"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="0dp" />
Colors XML:
Create your color in resource XML like below:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="green">#008000</color>
<color name="red">#FF0000</color>
<color name="yellow">#FFFF00</color>
</resources>
MainActivity Java file:
Create btnPressed method and check which colored button is clicked
public void btnPressed(View view) {
int colorId = ((ColorDrawable) view.getBackground()).getColor();
int greenColor = ContextCompat.getColor(getApplicationContext(), R.color.green);
if (greenColor == colorId) {
// Green colored button is clicked
// Do your code here
} else {
// Other colored button clicked
}
}
Hope this will be helpful!

Related

change tint of button programmatically

I simply want to change the backgroundTint of a normal button from inside the java code. I tried many different approaches like ColorStateList or setColorFilter, but nothing worked. I am purposefully not using setBackgroundColor since I want to keep the original shape of the button.
Furthermore, the colors I want to use are already defined in my resources. After lots of trial and error I managed to access these colors with this code:
int colorBtnDeactivated = ContextCompat.getColor(this, R.color.colorBtnDeactivated);
So basically I only need this one line of java code which enables me to access the background tint. The rest I can do myself.
I would really appreciate help, I have been stuck on this problem for hours. Thanks!
Edit: Using a selector-xlm didn't work, since it only changed the color of the button while being pressed. Also the buttons will influence each other, so by pressing one button I will need to be able to change the background tint of another button.
Edit 2: I tried again with setColorFilter:
//this is all inside the onCreate-method
int colorBtnActiveTest= ContextCompat.getColor(this, colorBtnActive);
int colorBtnDeactivatedTest=ContextCompat.getColor(this, colorBtnDeactivated);
Button btnKnockOne = (Button)findViewById(R.id.btnKnockOne);
boolean stateBtnKnockOne = false;
btnKnockOne.getBackground().setColorFilter(colorBtnDeactivatedTest, PorterDuff.Mode.SRC_IN);
btnKnockOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (stateBtnKnockOne==false){
btnKnockOne.getBackground().setColorFilter(colorBtnActiveTest, PorterDuff.Mode.SRC_IN);
stateBtnKnockOne=true;
}
else if (stateBtnKnockOne==true){
btnKnockOne.getBackground().setColorFilter(colorBtnDeactivatedTest, PorterDuff.Mode.SRC_IN);
stateBtnKnockOne=false;
}
}
});
This is the result:
When I open the activity, the button is displayed in the default grey button color, not in my custom color colorBtnDeactivatedTest
When I press the button, it briefly changes its color to colorBtnActiveTest, but then goes back to its grey color
I finally found a solution! This post helped me find it: https://stackoverflow.com/a/8748112/8952749
Now I basically have two buttons of which only one can be selected at one time. For this to work I created a selector-xlm:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="true"
android:drawable="#drawable/button_active" />
<item
android:state_selected="false"
android:drawable="#drawable/button_deactivated" />
</selector>
This is the java code, which enables me to change state_selected of the buttons:
stateBtn1=false;
stateBtn2=false;
btnTest1=(Button)findViewById(R.id.button);
btnTest2=(Button)findViewById(R.id.button2);
btnTest1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (stateBtn1==false){
btnTest1.setSelected(true);
stateBtn1=true;
btnTest2.setSelected(false);
stateBtn2=false;
}
else if (stateBtn1==true){
btnTest1.setSelected(false);
stateBtn1=false;
}
}
});
btnTest2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (stateBtn2==false){
btnTest2.setSelected(true);
stateBtn2=true;
btnTest1.setSelected(false);
stateBtn1=false;
}
else if (stateBtn2==true){
btnTest2.setSelected(false);
stateBtn2=false;
}
}
});

Android: checking a view's background

I have 3 buttons, all of them have the same background drawable by default (subject_button)
What I want to do:
When I click one button his background changes ( to clicked_subject), all the others remain with the default background, if I click one button after clicking another, the button I just clicked changes his background while the previous one gets back to the initial background, allowing only one button to have the clicked_subject background, if the diffrent button gets clicked again his background goes back to the initial one, leting all the buttons with the initial background.
The problem:
If I click the diffrent button, his background remains the same instead of changing back to the initial one.
My logic:
theButton1.setBackgroundResource(R.drawable.subject_button);
theButton1.setOnClickListener(this);
//same for other 2
#Override
public void onClick(View v) {
if (v.getBackground() == ContextCompat.getDrawable(this, R.drawable.subject_button)) {
theButton1.setBackgroundResource(R.drawable.subject_button);
theButton2.setBackgroundResource(R.drawable.subject_button);
theButton3.setBackgroundResource(R.drawable.subject_button);
v.setBackgroundResource(R.drawable.clicked_subject);
} else {
v.setBackgroundResource(R.drawable.subject_button);
}
Why is this happening?
You can do this:
private final List<Button> mButtons = new ArrayList<>();
// somewhere in your code
mButtons.add(mButton1);
mButtons.add(mButton2);
mButtons.add(mButton3);
mButton1.setOnClickListener(mClickListener);
mButton2.setOnClickListener(mClickListener);
mButton3.setOnClickListener(mClickListener);
private final View.OnClickListener mClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
for (Button button : mButtons) {
if (button == v) {
// set selected background
} else {
// set not selected backround
}
}
}
};
If you define a stateful drawable for your buttons, then you can simply change the onclick to this:
private final View.OnClickListener mClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
for (Button button : mButtons) {
button.setSelected(v == button);
}
}
};
For changing background color/image based on the particular event(focus, press, normal), you need to define a button selector file and implement it as background for button. For example button_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#drawable/your_image1" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="#drawable/your_image2" /> <!-- focused -->
android:drawable="#drawable/your_image3" <!-- default -->
</selector>
then just apply it as :
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawable="#drawable/button_selector.xml" />
I solved it by instead of changing only the background color on clicking the button, I also change the textColor, then I can check the textColor with if (((Button) v).getCurrentTextColor() == Color.WHITE)
"Pressed", "selected", "disabled" and such are View states. As such they're supposed to be handled automatically by Android and not by your click listeners.
This is achieved using SateLists, which control the look your Views sould have depending on which state(s) they're in. So you can easily set subject_button as the unpressed state, clicked_subject as the pressed state, and let Android take care of actually switching between them.
Full explanation: https://developer.android.com/guide/topics/resources/drawable-resource.html#StateList

How to adjust size of second image from setImageResource()

I am new to java/android and am making a test app. It has ImageButtons that when clicked switch to a different image temporarily. The originals are cropped using
android:adjustViewBounds="true"
android:scaleType="centerCrop"
in the activity_main.xml
The problem is the second image isnt cropped and is therefore too big for the button. DOes anyone know how I can fix this? HEres a an example of one of the buttons:
public void onClick(View v) {
//switch to second img
butt2.setImageResource(R.drawable.newimg);
//switch back to first after pause
new Handler().postDelayed(new Runnable() {
public void run() {
butt2.setImageResource(R.drawable.orig);
}
}, 500L);
}
});
I have used the following
int normal[] = { R.drawable.num0, R.drawable.num1, R.drawable.num2,
R.drawable.num3, R.drawable.num4, R.drawable.num5,
R.drawable.num6, R.drawable.num7, R.drawable.num8,
R.drawable.num9, R.drawable.del, R.drawable.go };
int pressed[] = { R.drawable.num0_clicked, R.drawable.num1_clicked,
R.drawable.num2_clicked, R.drawable.num3_clicked,
R.drawable.num4_clicked, R.drawable.num5_clicked,
R.drawable.num6_clicked, R.drawable.num7_clicked,
R.drawable.num8_clicked, R.drawable.num9_clicked,
R.drawable.del_clicked, R.drawable.go_clicked };
StateListDrawable sld;
for (int i = 0; i < 12; i++) {
sld = new StateListDrawable();
sld.addState(new int[] { android.R.attr.state_pressed },
getResources().getDrawable(pressed[i]));
sld.addState(new int[] {}, getResources().getDrawable(normal[i]));
btns[i].setImageDrawable(sld);
}
There's another way to attempt this thing , if you want like when you click the button its background should change and when you release it , background gets to previous one .
This can be achieved as follows
Now in your main.xml file that you want to show as an activity and where you have declared the button tag , add a statement
android:background="#drawable/customDefaultBackground"
and it will be like
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/customDefaultBackground" />
Now add an xml file of selector tag type and name it as customDefaultBackground.xml, open that file and add following to its contents :-
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" android:drawable="#drawable/onPressBackground" ></item>
<item android:drawable="#drawable/defaultBackground"></item>
</selector>
Item tag with android:state_pressed set to true , denotes that when a user clicks on a button and keep it pressed the backgroundOnPressed version will be displayed else it will show default background.

Temporarily swap image in button's background after click

I have prepared a two graphics for background of my button. I have one put in "android:background" in xml file and I have no idea how to make to change this image for another image for a while after click.
I tried to do this using OnHoverListener and OnClickListener but it doesn't work
Button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Button.setBackground(getResources().getDrawable(
R.drawable.img_hovered));
Button.setBackground(getResources().getDrawable(R.drawable.img));
}
});
if you want to make it clickable button, then make a selector xml in drawable folder and copy below code.
lets take its name as app_click.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/yourimage_pressed" android:state_pressed="true"/>
<item android:drawable="#drawable/yourimage_unpressed"/>
</selector>
then use this selector for your button Selector.
like this
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/app_click" />
See if the following does what you are looking for. The code assumes that R.drawable.img is the original background. When Button is clicked, the background changes to R.drawable.img_hovered for 0.5 seconds. Then it reverts back to R.drawable.img:
Button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Button.setBackground(getResources().getDrawable(
R.drawable.img_hovered));
new Handler().postDelayed(new Runnable() {
public void run() {
Button.setBackground(getResources().getDrawable(R.drawable.img));
// Button Click Code Here
}
}, 500L); // 0.5 Seconds
}
});

setBackgroundDrawable works correctly; until another button is pressed, why?

In my app I have 4 main buttons, plus another 2. These 4 buttons are declared at the beginning of the main activity.
Button button1, button2, button3, button4;
button1 = (Button) findViewById(R.id.button1);
button1.setTag("blue");
(each button has a tag and is set the same way as button1)
The four buttons I want to cycle through different colours when they are pressed. I manage this by;
public void button1(View v) {
if ("blue".equals(button1.getTag())) {
button1.setBackgroundDrawable(getResources().getDrawable(
R.drawable.brown));
button1.setTag("brown");
} else if ("brown".equals(button1.getTag())) {
button1.setBackgroundDrawable(getResources().getDrawable(
R.drawable.red));
button1.setTag("red");
} else if //...etc
This works all well and good until I press any of the two buttons, an example code of one of the buttons
public void back(View v) {
setContentView(R.layout.main);
t = new TextView(this);
t = (TextView) findViewById(R.id.textView1);
t.setText("");
}
Once I press any of the two buttons the colours change back to the original drawable set in the xml file
android:background="#drawable/blue"
Now when I press the 4 main buttons the drawable does not change, but I definitely know that it is getting re-tagged, so why won't it change the drawable after I press the button?
If your 'two buttons' onClick handler makes a call to Activity.setContentView(int), then all of the buttons will reset to how they are specified in the original XML layout. New views will be inflated and these will not have a tag (you do not seem to be re-setting the tags after the call to setContentView). A null tag will not match any of your colour strings and so your buttons will not cycle their background.
If you want to maintain the views how they were, then do not reset the content view of the Activity. In most cases, setContentView is only called once per lifetime of an Activity, although obviously there can be a few exceptions.

Categories