Home » Android » android button setPressed after onClick

android button setPressed after onClick

Posted by: admin May 14, 2020 Leave a comment

Questions:

yesterday I noticed the possibility to integrate Fragments in older API Levels through the Compatibility package, but thats not really essential for the question. 🙂

I have a Button with an OnClickListener

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        doSomething();
        button.setPressed(true);
    }
});

Because of the actual clicking, it is shown as pressed and after releasing the click, the button state is not pressed and stays that way.

Is there a simple way that keeps the button state pressed after releasing?
First thing I can think of would be some sort of timer, but that seems unreasonable.

How to&Answers:

You can keep the button states in xml file under drawable folder, then used as background for button.
For example:

 android:background="@drawable/buttonstate"

buttonstate.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/back_focused" />
    <item android:drawable="@drawable/back" /> <!-- default -->
</selector>

Answer:

Just to note this is because Android is changing the setPressed both before and after your onClickEvent, so changing it yourself has no effect. Another way to get around this is to use the onTouchEvent.

button.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        // show interest in events resulting from ACTION_DOWN
        if (event.getAction() == MotionEvent.ACTION_DOWN) return true;

        // don't handle event unless its ACTION_UP so "doSomething()" only runs once.
        if (event.getAction() != MotionEvent.ACTION_UP) return false;

        doSomething();
        button.setPressed(true);                    
        return true;
   }
});

Answer:

Use ToggleButton instead of Button.

<ToggleButton
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:background="@drawable/topping_selector"
    android:checked="false"
    android:textOff="Topping2"
    android:textOn="Topping2" />

topping_selector.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_checked="true" 
        android:drawable="@drawable/btn_topping_on" />

    <item android:state_checked="false" 
        android:drawable="@drawable/btn_topping_off" />

</selector>

Answer:

Better solution:

In xml file:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_activated="true">
        <bitmap android:src="@drawable/image_selected"/>
    </item>
    <item>
        <bitmap android:src="@drawable/image_not_selected"/>
    </item>
</selector>

And in java:

@Override
public void onClick(View v) {
   v.setActivated(!v.isActivated());
}

Answer:

You can use android.os.Handler class. Ugly, but works also:

final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        doSomething();
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                button.setPressed(true);
            }
        });
    }
});

Answer:

Another solution is to extend Button and override setPressed(boolean pressed) method so you can handle platform calls from the onClickEvent using a flag, for example changing the boolean pressed parameter depending on your needs.

public class MyButton extends Button {
   boolean isSelected = false;  //this is your flag
   @Override
   public void setPressed(boolean pressed) {
       if(isSelected) {
           //here you change the parameter so it stays pressed
           super.setPressed(true);
           return;
       }
       super.setPressed(pressed);
   }

   public void setIsSelected(boolean selected) {
       this.isSelected = selected;
   }

   public MyButton(Context context) {
       super(context);
   }
}

Answer:

This is the solution I used, It also works on android 7.0 at the moment.

YourActivity.java

public void onStandbyStart(String message) {
    startStandbyBtn.setActivated(true);
}

public void onBackOnline(String message) {
    startStandbyBtn.setActivated(false);
}

YourActivityLayout

<Button
        ...
        style="@style/generic_btn_style"
        ... />

values/styles.xml

    <style name="generic_btn_style" parent="@android:style/Widget.Button">
        <item name="android:gravity">center_vertical|center_horizontal</item>
        <item name="android:background">@drawable/generic_btn</item>
        <item name="android:textColor">@color/selector_white_black</item>
        <item name="android:focusable">true</item>
        <item name="android:clickable">true</item>
</style>

drawable/generic_btn.xml
This selector chooses the button background. I use the pressed as the activated.

<?xml version="1.0" encoding="utf-8"?>

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/generic_btn_disabled" android:state_enabled="false" />
    <item android:drawable="@drawable/generic_btn_pressed" android:state_enabled="true" android:state_pressed="true" />
    <item android:drawable="@drawable/generic_btn_pressed" android:state_activated="true" />
    <item android:drawable="@drawable/generic_btn_focused" android:state_enabled="true" android:state_focused="true" />
    <item android:drawable="@drawable/generic_btn_enabled" android:state_enabled="true" />
</selector>

color/selector_black_white
Here I set the text color. In my case, I need to pick the textcolor black when pressed.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#fff" android:state_pressed="true" /> <!-- pressed -->
    <item android:color="#fff" android:state_activated="true" /> <!-- pressed -->
    <item android:color="#000" /> <!-- default -->
</selector>