How to set a gradient background in a Material Button from Material Components?
Asked Answered
L

6

12

I've been trying to set a gradient background in a Material Button from Material Components for Android, but it's not working. So, how to set a gradient background in a Material Button?

Lithomarge answered 20/10, 2018 at 17:0 Comment(1)
That isn't possible to easily change background color to a gradient currently. The only way you could achieve that is by creating your own gradient drawable and setting that to the material button.Unilobed
F
18

From the documentation for MaterialButton:

Do not use the android:background attribute. MaterialButton manages its own background drawable, and setting a new background means MaterialButton can no longer guarantee that the new attributes it introduces will function properly. If the default background is changed, MaterialButton cannot guarantee well-defined behavior.

The only supported way to modify the background of the button is to set a color value to the app:backgroundTint attribute. Unfortunately, gradients are not supported here either; you can only use a simple color value or a ColorStateList.

So, there is no supported way to use a gradient background with MaterialButton.

Fredrika answered 12/11, 2018 at 22:35 Comment(0)
T
26

Starting with the version 1.2.0-alpha06 you can use the android:background attribute in the MaterialButton.

<MaterialButton
    app:backgroundTint="@null"
    android:background="@drawable/button_gradient"
    ... />

Otherwise if you can't use the 1.2.0-alpha06 or higher you have to use the AppCompatButton component.

Just a some tips about the MaterialButton.

  • Currently the backgroundTint is still the default MaterialButton style.
    If you are using a custom android:background, you have to make sure to null out backgroundTint (either app:backgroundTint="@null" or app:backgroundTint="@empty"), to avoid that the custom background doesn't get tinted.
  • using a custom android:background the default MaterialShapeDrawable is not used. Some features like stroke, shapeappearance, ripple are not set (since they are related to the MaterialShapeDrawable) . You have to provide them with your custom background.
Threlkeld answered 5/5, 2020 at 10:5 Comment(4)
had to come back to see the backgroundTint tip. This is key! I put a gradient on my button and it had the wrong colors. Thanks for that pointer.Clothespress
I lost ripple color effect on a button on which I used this method. Do you know how to save ripple effect?Trici
@Trici Using a custom background you are removing the ShapeMaterialDrawable which handles also the ripple. You have to apply a custom RippleDrawable to your background.Threlkeld
@GabrieleMariotti I changed my drawable_background.xml that contained only shape, to <ripple> xml, that contained either shape and ripple items :) Works great, thanks!Trici
F
18

From the documentation for MaterialButton:

Do not use the android:background attribute. MaterialButton manages its own background drawable, and setting a new background means MaterialButton can no longer guarantee that the new attributes it introduces will function properly. If the default background is changed, MaterialButton cannot guarantee well-defined behavior.

The only supported way to modify the background of the button is to set a color value to the app:backgroundTint attribute. Unfortunately, gradients are not supported here either; you can only use a simple color value or a ColorStateList.

So, there is no supported way to use a gradient background with MaterialButton.

Fredrika answered 12/11, 2018 at 22:35 Comment(0)
S
5

Make use of androidx.appcompat.widget.AppCompatButton if you are using Material Theme to be able to apply background gradients, because Material Button doesn't offer support to it yet.

For background gradient, create 3 new resources in drawable folder:

selector_btn.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- disabled state -->
    <item android:drawable="@drawable/btn_gradient_inactive" android:state_enabled="false" />
    <item android:drawable="@drawable/btn_gradient_active" />
</selector>

btn_gradient_inactive.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:startColor="#01579B"
        android:endColor="#1A237E"
        android:angle="0" />
    <corners android:radius="5dp"/> </shape>

btn_gradient_active.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:startColor="#2196F3"
        android:endColor="#3F51B5"
        android:angle="0" />
    <corners android:radius="5dp"/>
</shape>

In your styles.xml:

<style name="BtnStyle" parent="Widget.AppCompat.Button.Borderless">
    <item name="android:layout_marginStart">35dp</item>
    <item name="android:layout_marginEnd">35dp</item>
    <item name="android:background">@drawable/selector_btn_gradient</item>
    <item name="android:textColor">@color/selector_text_color</item>
    <item name="android:textAllCaps">false</item>
    <item name="android:textSize">14sp</item>
</style>

In your layout.xml file:

<androidx.appcompat.widget.AppCompatButton
    android:id="@+id/my_btn_id"
    style="@style/BtnStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
Shrimp answered 20/8, 2019 at 19:45 Comment(0)
R
5

I found this solution.

<com.google.android.material.button.MaterialButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:background="@drawable/selector_gradient_example"
      app:backgroundTint="@null" />

selector_gradient_example

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/banana_yellow">
    <item android:state_enabled="true">
        <ripple android:color="@color/banana_yellow">
            <item>
                <shape android:shape="rectangle">
                    <gradient android:angle="135" android:endColor="@color/banana_yellow" android:startColor="@color/main_yellow" />
                </shape>
            </item>
        </ripple>
    </item>
    <item android:state_enabled="false">
        <shape android:shape="rectangle">
            <gradient android:angle="315" android:endColor="#ede0be" android:startColor="#e0bf7e" />
        </shape>
    </item>
</selector>
Rubio answered 24/9, 2020 at 14:24 Comment(2)
Hi, and welcome to StackOverflow! Answers should not be simple snippets of code. Can you elaborate on why and how this code answers the question?Skeleton
This solution works since app:backgroundTint has no effect even if set with drawable. Setting the background to drawable gradient and app background tint, makes the gradient work on the buttonCollenecollet
U
0

Removing backgroundTint attribute in xml worked for me.

Urdar answered 5/4, 2022 at 11:22 Comment(0)
B
-1

btn_gradient.xml

    <?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:startColor="#469FED"
        android:angle="90"
        android:endColor="#2AC88D"/>
    <corners android:radius="4dp"/>
</shape>

and use this instead of a button:

    <RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="5dp"
                android:clickable="true"
                android:focusable="true"
                android:background="@drawable/btn_gradient">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:minHeight="40dp"
                    android:background="?attr/selectableItemBackground"
                    android:padding="5dp"
                    android:text="send" />
 </RelativeLayout>
Bandwidth answered 21/1, 2020 at 10:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.