0

On Android, a Button changes its background color when pressed.

How can we tell a button that it is pressed (without firing the onClick-action), so that it changes color, without the user pressing it? (for example triggered by a swipe action)

It should change color briefly, and then change back.

There a quite a few questions concerning keeping the pressed state. This question asks, how to set the button_pressed state briefly, as if clicked, but without a real click.

Button.setPressed(true) has not given a color change, neither has Button.performClick().

Community
  • 1
  • 1
serv-inc
  • 35,772
  • 9
  • 166
  • 188
  • 1
    haaaay then will it be fine for you to do long way illusion? I mean, we use asynctask, in preExecute(), we do btn.setBackgroundDrawable. . .pressed, in doInBackground, we do Thread.sleep(1000);, then in postExecute(), we do btn.setBackgroundDrawable. . .normal. . . with the action you want to do.. – Sheychan Jul 10 '15 at 09:15
  • That sounds good. A built-in `Button` action would be nicer, but if it does not exist, that seems very workable. – serv-inc Jul 10 '15 at 09:17

4 Answers4

4

To change a button state without anything else is done via

btn1.getBackground().setState(new int[]{android.R.attr.state_pressed});

To reset to ordinary, you use

btn1.getBackground().setState(new int[]{android.R.attr.state_enabled});

A Button's states can be found out via

btn1.getBackground().getState();

which resturns an int[]. You can compare its values to android.R.attr to find out which states are set.

Example Code

private void simulateClick(final ImageButton button,
                           final long clickDuration) {
    button.getBackground().setState(new int[]{android.R.attr.state_pressed});
    new Thread(new Runnable() {
        public void run() {
            try {
                Thread.sleep(clickDuration);
            } catch ( InterruptedException e ) {
                // not bad if interrupted: sleeps a bit faster (can happen?)
            }
            Count.this.runOnUiThread(new Runnable() {
                    public void run() {
                        button.getBackground().setState(new int[]{android.R.attr.state_enabled});
                    }
                });
        }}).start();
}

Explanation

Each View has a Drawable as background image. A Drawable can be of different subtypes, here it is a StateListDrawable, as defined per XML. (See @Lynx's answer as an example of a XML defined drawable).

This Drawable can be told which state it is to assume (via setState) and does the layout itself.

Community
  • 1
  • 1
serv-inc
  • 35,772
  • 9
  • 166
  • 188
3

First, create the effect when button is hovered, clicked etc in XML. Put this style in your drawable.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Pressed button -->
    <item android:drawable="@color/dark_green"
        android:state_focused="true"
        android:state_pressed="false"
        />
    <item android:drawable="@color/dark_green"
        android:state_focused="true"
        android:state_pressed="true"
        />
    <item android:drawable="@color/dark_green"
        android:state_focused="false"
        android:state_pressed="true"/>

    <!-- Normal button -->
    <item android:drawable="@color/green"
        android:state_focused="false"
        android:state_pressed="false"/>
</selector>

Then in your XML, initiates the style by using:

<Button
 android:layout_width="wrap_content"
 android:layout_height="match_parent"
 android:background="@drawable/the_style_in_drawable"
 android:text="click"/>

By putting the style in your XML, you don't have to initiate the style when button on click. Android will detect the button state and do the work for you. Just remember to put the state in selector.

Lynx
  • 131
  • 9
  • The question was unclear. It asked about not pressing but only doing the animation. Still, the `state_pressed` helped. – serv-inc Jul 10 '15 at 11:48
2

AsyncTask for button color change illusion:

private class ChangeButtonColorMomentarily extends AsyncTask<String, Void, String> {

    @Override
    protected void onPreExecute() {
        btn1.setBackgroundDrawable(new ColorDrawable(Color.rgb(50, 50, 50)));//pressed state
    }

    @Override
    protected String doInBackground(String... params) {
        try {
            Thread.sleep(1000);
        } catch (Exception e) {

        }
        return "";
    }

    @Override
    protected void onPostExecute(String result) {
        btn1.setBackgroundDrawable(new ColorDrawable(Color.rgb(200, 200, 200)));//normal state
    }

}

Also take note that if your API 16 above use setBackground() instead.

Sheychan
  • 2,415
  • 14
  • 32
  • Thank you. It works for changing the color and back. Does the `Button` in your App look just like the original, after `onPostExecute`, or is it just a grey square? – serv-inc Jul 10 '15 at 09:53
  • No, this is just an example/basis., we can use other resource drawables. – Sheychan Jul 10 '15 at 10:01
  • 1
    You can use `btn1.getBackground().setState(new int[]{android.R.attr.state_pressed});` to set the pressed state and `btn1.getBackground().setState(new int[]{android.R.attr.state_enabled});` to resume the *normal* state afterwards. The `Drawable`hint helps and the `AsyncTask` is a nice approach. – serv-inc Jul 10 '15 at 10:47
1

For changing the color of button at that time, you can use setOnTouchListener as:

button.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_DOWN){
                //Button Pressed
            }
            if(event.getAction() == MotionEvent.ACTION_UP){
                 //finger was lifted
            }
            return false;
        }
    });
Anshul Tyagi
  • 2,076
  • 4
  • 34
  • 65
  • Thank you for the contribution. I did not say it clearly enough. The question was what to do when the button is *not* pressed, but the color needs to be changed as if. – serv-inc Jul 10 '15 at 08:45
  • 1
    If you want to change color of button without clicking on it you can use flags. – Anshul Tyagi Jul 10 '15 at 08:57
  • flags work, see the comment to [@Sheychan's answer](http://stackoverflow.com/a/31337240/1587329) – serv-inc Jul 10 '15 at 11:12
  • 1
    There are so many ways to do it. Btw it feels good to hear that your problem is solved. – Anshul Tyagi Jul 10 '15 at 11:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/82940/discussion-between-anshul-tyagi-and-user1587329). – Anshul Tyagi Jul 10 '15 at 11:56