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
Related
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!
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;
}
}
});
I'm using a simple ListView for my navigation drawer, with android:choiceMode="singleChoice" set in the layout XML. This allows me to use a selector for the text color:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:color="#color/primary_500" />
<item android:color="#color/text_primary" />
</selector>
Which will color the selected item with primary_500 and the rest with text_primary.
The above is working fine, but one of the items will launch a new activity instead of loading a fragment, so it should never be made the ListView's selected item.
I've tried reverting it with this:
public void selectItem( int index ) { selected_item = index; }
public void revertSelectedItem() {
int y = navigation.getScrollY();
list.setSelection( selected_item );
list.scrollTo( 0, y );
}
And elsewhere:
#Override
public void onItemClick( ListView list, View view, int index, long id ) {
switch( (int)id ) {
case R.id.exampleItem_forFragment:
/* Swap fragments */
selectItem( index );
break;
case R.id.exampleItem_forActivity:
/* Launch activity */
revertSelectedItem();
break;
}
}
But, even though revertSelectedItem() is called, the selection does not change. I'm presuming that the new selection is not assigned until after onItemClick() returns, so my change is getting overwritten.
Is there a clean way to disable or revert selection changes for only certain items, but still receive click events?
Seems I just misunderstood the purpose of some methods. Changing revertSelectedItem() to look like this:
public void revertSelectedItem() {
list.setItemChecked( selected_item, true );
}
behaves exactly like I want. It looks like ListView uses the item's "checked" state, rather than the selection, to decide which items are marked. When in choiceMode="singleChoice", calling setItemChecked() also unchecks all other items automatically.
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.
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
}
});