Android, setting the background color of the button loses ripple effect

After adding color to the android button, it loses the ripple effect, which makes the user feel like there is a responsive click. How to fix it? I searched for a lot of solutions, but I could not find a specific one that was not ambiguous.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ClockInOutFragment"> <AnalogClock android:id="@+id/clock" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/date_and_time"/> <RelativeLayout android:id="@+id/date_and_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp"> <TextView android:id="@+id/time_digits" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="12:10" android:textSize="45sp"/> <TextView android:id="@+id/am_pm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/time_digits" android:layout_toRightOf="@+id/time_digits" android:paddingLeft="3dp" android:text="PM" android:textSize="20sp"/> <TextView android:id="@+id/date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/time_digits" android:text="Mon, July 11" android:textSize="22sp"/> </RelativeLayout> <!--Clock in and out buttons--> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:orientation="horizontal"> <Button android:id="@+id/textView3" android:layout_width="0dp" android:layout_height="56dp" android:layout_weight="1" android:background="#4CAF50" android:gravity="center" android:text="Clock In" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="#FFFFFF"/> <!--Divider between the clock in and out button--> <View android:layout_width="1dp" android:layout_height="match_parent" android:background="#B6B6B6"/> <Button android:id="@+id/textView4" android:layout_width="0dp" android:layout_height="56dp" android:layout_weight="1" android:background="#FF5252" android:gravity="center" android:text="Clock Out" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="#FFFFFF"/> </LinearLayout> </RelativeLayout> 
+17
android button click ripple effect
source share
6 answers

You can add ripple effect and background color with additional ripples:

your layout:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button_connect" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="20dip" android:fontFamily="sans-serif" android:text="Connect" android:background="@drawable/ripple" android:textColor="#FFFFFF" android:textSize="18sp" /> </LinearLayout> 

ripple.xml (here you can add the background color in addition to the ripple effect):

 <?xml version="1.0" encoding="utf-8"?> <!-- in drawable folder--> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:colorControlHighlight"> <item android:id="@android:id/mask"> <shape android:shape="rectangle"> <solid android:color="?android:colorAccent" /> </shape> </item> <item> <shape android:shape="rectangle"> <!-- put your background color here--> <solid android:color="@color/default_color" /> </shape> </item> </ripple> 
+24
source share

A very simple and direct way to do this is to set the ?attr/selectableItemBackground in android:foreground your button. The following xml works fine and works

 <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/white" android:foreground="?attr/selectableItemBackground"/> 
+18
source share

Do not change the button background. Change the theme.

 <style name="ButtonGray"> <item name="colorButtonNormal">@color/gray</item> </style> 

and in your xml file

 <Button android:id="@+id/accept_button" android:layout_height="wrap_content" android:layout_width="0dp" android:layout_weight="1" android:text="@string/button_accept_group" android:theme="@style/ButtonGray"/> 

Or you can add it to your main application theme

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorButtonNormal">@color/primary_color</item> </style> 

And no need to change the background of the button.

If you need a fully customizable background, you need to create your own selector. And you can set the ripple effect.

+13
source share

Just use:

 android:backgroundTint="#4CAF50" 

Instead:

 android:background="#4CAF50" 

Remember to change Button to android.support.v7.widget.AppCompatButton

+4
source share

In fact, you can use <layer-list> for drawing to combine the ripple effect with any other drawing. This universal solution is also for pre-lolipop: I tested it in many configurations.

The only problem is that pre-lolipop crashes when ?selectableItemBackground SelectableItemBackground SelectableItemBackground appears inside the <layer-list> , so we need to create a LayerDrawable programmatically.

A very quick simple solution looks like this:

Specify for your viewing

 android:background="?selectableItemBackground" 

Then, anywhere in the code, create mySpecialDrawable and do your job:

 Drawable[] layers = {mySpecialDrawable, getBackground()}; setBackgroundDrawable(new LayerDrawable(layers).mutate()); 

Please note that .mutate() for LayeredDrawable is very important here!

A more complex solution may be useful when you already have a custom view, and you prefer to expand its functionality and compatibility rather than add an additional empty FrameLayout as a parent.

Inside attrs.xml put:

 <resources> <declare-styleable name="MyView"> <attr name="selectableBackground" format="reference"/> <attr name="backgroundDrawable" format="reference"/> </declare-styleable> </resources> 

then inside your descendant class:

 private Drawable selectableBackground; private Drawable backgroundDrawable; public MyView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); try { TypedArray attributeArray; attributeArray = context.obtainStyledAttributes(attrs, R.styleable.MyView); int id = attributeArray.getResourceId(R.styleable.MyView_selectableBackground, -1); if (id != -1) { selectableBackground = ResourcesCompat.getDrawable(getResources(), id, context.getTheme()); } id = attributeArray.getResourceId(R.styleable.MyView_backgroundDrawable, -1); if (id != -1) { backgroundDrawable = ResourcesCompat.getDrawable(getResources(), id, context.getTheme()); } constructBackground(); attributeArray.recycle(); } catch (Exception e) { Log.e(this.toString(), "Attributes initialization error", e); throw e; } } void setSelectableBackground(Drawable drawable) { selectableBackground = drawable; constructBackground(); } void setDrawable(Drawable drawable) { backgroundDrawable = drawable; constructBackground(); } private void constructBackground() { if (selectableBackground != null) { if (backgroundDrawable != null) { Drawable[] layers = {backgroundDrawable, selectableBackground}; setBackgroundDrawable(new LayerDrawable(layers).mutate()); // Both, using layers } else setBackgroundDrawable(selectableBackground); // Selectable only } else setBackgroundDrawable(backgroundDrawable); // Background only or null } 

I prefer this approach because it does not have problems such as the android:foreground attribute which is 23+, or the additional overhead of including interactive views inside FrameLayout.

0
source share

You have to use styles

 <style parent="Theme.AppCompat.Light" name="RaisedButtonGreen"> <item name="colorButtonNormal">@color/green</item> <item name="colorControlHighlight">@color/greenLight</item> <item name="android:textColor">@android:color/white</item> </style> 

this is the best solution

 <Button android:layout_width="match_parent" android:layout_height="match_parent" android:text="Button with ripple for style" android:theme="@style/RaisedButtonGreen"/> 
-one
source share

All Articles