Jignesh Ansodariya
Jignesh Ansodariya

Reputation: 12685

How to set button click effect in Android?

In Android, when I set a background image to a button, I can not see any effect on it when it's clicked.

I need to set some effect on the button, so the user can recognise that the button is clicked.

The button should be dark for a few seconds when it is clicked. How to do this?

Upvotes: 132

Views: 317366

Answers (17)

Anil Pandey
Anil Pandey

Reputation: 1

I tried something to set button click effect in android- 1.I created a animation resource file to use as button click effect. 2.Created a animation listener. 3.On animation end I can set the task or activity which I want to start on button click. 4.Then set animation on button.

<scale
    android:duration="90"
    android:fromYScale="0.9"
    android:fromXScale="0.9"
    android:toYScale="1.0"
    android:toXScale="1.0"
    android:pivotY="50%"
    android:pivotX="50%"/>


Animation animationButton = AnimationUtils.loadAnimation(MyActivity.this,R.anim.bounce_button);

 animationButton.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }
            @Override
            public void onAnimationEnd(Animation animation) {
                Intent intent = new Intent(getApplicationContext(),SecondActivity.class);
                startActivity(intent);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                button.startAnimation(animationButton);


            }
        });

'''
I hope this will help.

Upvotes: 0

Ljdawson
Ljdawson

Reputation: 12229

This can be achieved by creating a drawable xml file containing a list of states for the button. So for example if you create a new xml file called "button.xml" with the following code:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/YOURIMAGE" />
    <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/gradient" />
    <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/gradient" />
    <item android:drawable="@drawable/YOURIMAGE" />
</selector>

To keep the background image with a darkened appearance on press, create a second xml file and call it gradient.xml with the following code:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <bitmap android:src="@drawable/YOURIMAGE"/>
    </item>
    <item>
        <shape xmlns:android="http://schemas.android.com/apk/res/android">
            <gradient android:angle="90" android:startColor="#880f0f10" android:centerColor="#880d0d0f" android:endColor="#885d5d5e"/>
        </shape>
    </item>
</layer-list>

In the xml of your button set the background to be the button xml e.g.

android:background="@drawable/button"

Changed the above code to show an image (YOURIMAGE) in the button as opposed to a block colour.

Upvotes: 173

Kumar Santanu
Kumar Santanu

Reputation: 701

Simple and easy way to set View click effect.

Method

public AlphaAnimation clickAnimation() {
    return new AlphaAnimation(1F, 0.4F); // Change "0.4F" as per your recruitment.
}

Set in View

yourView.startAnimation(clickAnimation());

Upvotes: 3

MandelMech
MandelMech

Reputation: 507

I had the same issue, where I needed to have a transparent background but still get animation. Setting this solved it for me:

android:background="?android:selectableItemBackground"

Also this if you want to have circular effect:

android:background="?android:selectableItemBackgroundBorderless"

Upvotes: 4

Arpit Patel
Arpit Patel

Reputation: 8047

Create bounce.xml file fo animation

LOCATION:

res->anim->bounce.xml

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

    <scale
        android:duration="100"
        android:fromXScale="0.9"
        android:fromYScale="0.9"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0" />

</set>

Add this line in onClick to initialize

  final Animation myAnim = AnimationUtils.loadAnimation(this,R.anim.bounce);
         button.startAnimation(myAnim);

You get the shrink effect in a button click.

Upvotes: 2

Faizan Haidar Khan
Faizan Haidar Khan

Reputation: 1215

For all the views

android:background="?android:attr/selectableItemBackground"

But for cardview which has elevation use

android:foreground="?android:attr/selectableItemBackground"

For Circular click effect as in toolbar

android:background="?android:attr/actionBarItemBackground"

Also you need to set

 android:clickable="true"
 android:focusable="true"

Upvotes: 11

Ely Dantas
Ely Dantas

Reputation: 705

To make your item consistent with the system look and feel try referencing the system attribute android:attr/selectableItemBackground in your desired view's background or foreground tag:

<ImageView
    ...
    android:background="?android:attr/selectableItemBackground"      
    android:foreground="?android:attr/selectableItemBackground"
    ...
/>

Use both attributes to get desired effect before/after API level 23 respectively.

https://stackoverflow.com/a/11513474/4683601

Upvotes: 27

Francis
Francis

Reputation: 7104

You can simply use foreground for your View to achieve clickable effect:

android:foreground="?android:attr/selectableItemBackground"


For use with dark theme add also theme to your layout (to clickable effect be clear):

android:theme="@android:style/ThemeOverlay.Material.Dark"

Upvotes: 96

giang nguyen
giang nguyen

Reputation: 423

Use RippleDrawable for Material Design state pressed/clicked effect.

In order to achieve this, create ripple item as an .xml under /drawable folder and use it in android:background for any views.

  • Effect for icon pressed/clicked, use circular ripple effect, for example:

    <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@android:color/darker_gray" />

  • Effect for view clicked with rectangle boundary, we can add ripple over the existing drawable like bellow:

    <?xml version="1.0" encoding="utf-8"?> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#000000"> <item android:drawable="@drawable/your_background_drawable"/> </ripple>

Upvotes: 2

Andr&#225;s
Andr&#225;s

Reputation: 3475

It is simpler when you have a lot of image buttons, and you don't want to write xml-s for every button.

Kotlin Version:

fun buttonEffect(button: View) {
    button.setOnTouchListener { v, event ->
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                v.background.setColorFilter(-0x1f0b8adf, PorterDuff.Mode.SRC_ATOP)
                v.invalidate()
            }
            MotionEvent.ACTION_UP -> {
                v.background.clearColorFilter()
                v.invalidate()
            }
        }
        false
    }
}

Java Version:

public static void buttonEffect(View button){
    button.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.getBackground().clearColorFilter();
                    v.invalidate();
                    break;
                }
            }
            return false;
        }
    });
}

Upvotes: 95

RastaPopuloS
RastaPopuloS

Reputation: 3

If you're using xml background instead of IMG, just remove this :

<item>
    <bitmap android:src="@drawable/YOURIMAGE"/>
</item>

from the 1st answer that @Ljdawson gave us.

Upvotes: 0

dzboot02
dzboot02

Reputation: 2980

Making a minor addition to Andràs answer:

You can use postDelayed to make the color filter last for a small period of time to make it more noticeable:

        @Override
        public boolean onTouch(final View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            v.getBackground().clearColorFilter();
                            v.invalidate();
                        }
                    }, 100L);
                    break;
                }
            }
            return false;
        }

You can change the value of the delay 100L to suit your needs.

Upvotes: 0

Vinayak Bevinakatti
Vinayak Bevinakatti

Reputation: 40503

Or using only one background image you can achive the click effect by using setOnTouchListener

Two ways

((Button)findViewById(R.id.testBth)).setOnTouchListener(new OnTouchListener() {

      @Override
        public boolean onTouch(View v, MotionEvent event) {
          switch (event.getAction()) {
              case MotionEvent.ACTION_DOWN: {
                  Button view = (Button) v;
                  view.getBackground().setColorFilter(0x77000000, PorterDuff.Mode.SRC_ATOP);
                  v.invalidate();
                  break;
              }
              case MotionEvent.ACTION_UP:
                  // Your action here on button click
              case MotionEvent.ACTION_CANCEL: {
                  Button view = (Button) v;
                  view.getBackground().clearColorFilter();
                  view.invalidate();
                  break;
              }
          }
          return true;
        }
});

enter image description here

And if you don't want to use setOnTouchLister, the another way of achieving this is

    myButton.getBackground().setColorFilter(.setColorFilter(0xF00, Mode.MULTIPLY);

    StateListDrawable listDrawable = new StateListDrawable();
    listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
    listDrawable.addState(new int[] {android.R.attr.defaultValue}, myButton);

    myButton.setBackgroundDrawable(listDrawable);

Upvotes: 11

Ehtesham Hasan
Ehtesham Hasan

Reputation: 4153

This is the best solution I came up with taking hints from @Vinayak's answer. All the other solutions have different drawbacks.

First of all create a function like this.

void addClickEffect(View view)
{
    Drawable drawableNormal = view.getBackground();

    Drawable drawablePressed = view.getBackground().getConstantState().newDrawable();
    drawablePressed.mutate();
    drawablePressed.setColorFilter(Color.argb(50, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);

    StateListDrawable listDrawable = new StateListDrawable();
    listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
    listDrawable.addState(new int[] {}, drawableNormal);
    view.setBackground(listDrawable);
}

Explanation:

getConstantState().newDrawable() is used to clone the existing Drawable otherwise the same drawable will be used. Read more from here: Android: Cloning a drawable in order to make a StateListDrawable with filters

mutate() is used to make the Drawable clone not share its state with other instances of Drawable. Read more about it here: https://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate()

Usage:

You can pass any type of View (Button, ImageButton, View etc) as the parameter to the function and they will get the click effect applied to them.

addClickEffect(myButton);
addClickEffect(myImageButton);

Upvotes: 4

Ahmed Adel Ismail
Ahmed Adel Ismail

Reputation: 2184

Create your AlphaAnimation Object that decides how much will be the fading effect of the button, then let it start in the onClickListener of your buttons

For example :

private AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);

// some code

public void onClick(View v) {
    v.startAnimation(buttonClick);
}

of course this is just a way, not the most preferred one, it's just easier

Upvotes: 94

Vinod Joshi
Vinod Joshi

Reputation: 7862

Step: set a button in XML with onClick Action:

 <Button
android:id="@+id/btnEditUserInfo"
style="?android:borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="@dimen/txt_height"
android:layout_gravity="center"
android:background="@drawable/round_btn"
android:contentDescription="@string/image_view"
android:onClick="edit_user_info"
android:text="Edit"
android:textColor="#000"
android:textSize="@dimen/login_textSize" />

Step: on button clicked show animation point
//pgrm mark ---- ---- ----- ---- ---- ----- ---- ---- -----  ---- ---- -----

    public void edit_user_info(View view) {

        // show click effect on button pressed
        final AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);
        view.startAnimation(buttonClick);

        Intent intent = new Intent(getApplicationContext(),  EditUserInfo.class);
        startActivity(intent);

    }// end edit_user_info

Upvotes: 3

arianoo
arianoo

Reputation: 667

just wanna add another easy way to do this: If your ImageButton remains its background and you don't set it to null, it will work like a normal button and will show the click animation while clicking exactly like other buttons.The way to hide the background while it is still there:

<ImageButton
    android:id="@+id/imageButton2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingBottom="1dp"
    android:paddingLeft="1dp"
    android:paddingRight="1dp"
    android:paddingTop="1dp"
    android:src="@drawable/squareicon" />

The paddings won't let the background be visible and make the button act like other buttons.

Upvotes: 3

Related Questions