Buttons are one of the key interface elements in Android applications, and their appearance directly affects the user experience. Even a standard button Button iz Android SDK can look different depending on the OS version, application theme and device. But what if the designer sent a layout with non-standard rounded buttons, gradients or animations? Or if you need to adapt the interface to the corporate style of the brand?

In this article we will look all possible ways to change buttons in Android Studio โ€”from simple customization via XML to dynamically changing styles in the code Kotlin/Java. You will learn how to work with attributes, create custom resources, apply and even animate button interaction. We will pay special attention to typical errors that lead to incorrect display on different versions of Android. style, create custom drawable-resources to apply Material Design and even animate button interaction. We will pay special attention to typical errors that lead to incorrect display on different versions of Android.

If you are just starting to develop for Android, do not be alarmed: we will start with basic methods and gradually move on to advanced techniques. Experienced developers will also find useful tricks here - for example, how to integrate buttons with Jetpack Compose or use vectors for adaptive icons.

Before you begin, make sure that you have the latest version Android Studio Giraffe (or newer) and the latest dependencies installed build.gradle. Some code examples require a library Material Components, which we will include in the first section.

๐Ÿ“Š What type of buttons do you most often use in projects?
Standard (Button, ImageButton)
MaterialButton
Custom (created through XML/drawable)
Buttons in Jetpack Compose

1. Basic ways to change a button via XML

Let's start with the simplest thing - modifying a standard button <Button> directly in the markup file (activity_main.xml or fragment_layout.xml). Even without creating separate styles or resources, you can change:

  • ๐ŸŽจ Background color text (android:background, android:textColor)
  • ๐Ÿ“ Dimensions and padding (android:layout_width, android:padding)
  • ๐Ÿ”„ Fillet corners (via shape drawable)
  • ๐Ÿ–ผ๏ธ Icons (using android:drawableLeft)

Example of minimal customization:

<Button

android:id="@+id/myButton"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Click me"

android:textColor="#FFFFFF"

android:background="#6200EE"

android:paddingStart="24dp"

android:paddingEnd="24dp"

android:textAllCaps="false"/>

Please note to the attribute textAllCaps="false" โ€” by default, Android converts text buttons in upper case. Also avoid strictly specifying colors in the markup: it is better to put them in colors.xml for convenient theme management.

To round corners, create a file rounded_button.xml in a folder res/drawable:

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

android:shape="rectangle">

<solid android:color="#6200EE"/>

<corners android:radius="8dp"/>

<padding android:left="16dp" android:right="16dp"/>

</shape>

Then apply it to the button via android:background="@drawable/rounded_button".

๐Ÿ’ก

To make the button look the same on all versions of Android, use android:minHeight="48dp" โ€”this is the minimum recommended height for comfortable finger pressing.

2. Styles and themes: how not to repeat the code for each button

If your application has dozens of buttons with the same design, duplicating attributes in each markup is a bad practice. Instead, create a style in the file in the file res/values/styles.xml:

<style name="CustomButtonStyle" parent="Widget.AppCompat.Button">

<item name="android:textColor">@color/white</item>

<item name="android:background">@drawable/rounded_button</item>

<item name="android:paddingVertical">12dp</item>

<item name="android:paddingHorizontal">24dp</item>

<item name="android:textAllCaps">false</item>

</style>

Now apply the style to all buttons via style="@style/CustomButtonStyle"For global change. (for example, make all the buttons in the application round) modify the theme V styles.xml:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

<item name="buttonStyle">@style/CustomButtonStyle</item>

</style>

This will automatically apply the style to all standard buttons (Button) in the application (we'll talk about it later) use MaterialButton (we'll talk about it later) use materialButtonStyle.

โš ๏ธ Attention: If you override the style of a button via a theme, but some buttons need to look different, explicitly specify style="@style/AnotherButtonStyle"for them, otherwise they will inherit the global settings.
Style attribute Description Example value
android:background Button background (color or drawable) @drawable/rounded_button or #6200EE
android:textColor Text color @color/white or #FFFFFF
android:fontFamily Font text @font/roboto_medium
cornerRadius Rounding corners (for MaterialButton) 8dp

3. MaterialButton: modern buttons from Google

Library Material Components for Android offers an expanded set of widgets, including com.google.android.material.button.MaterialButton. supports:

  • ๐ŸŽฏ Icons (via app:icon)
  • ๐Ÿ”„ States (pressed, disabled, with focus)
  • ๐Ÿ–Œ๏ธ Styles (filled, outline, text)
  • ๐ŸŽจ Animations (ripple effect, color change)

First add a dependency to build.gradle (Module: app):

implementation 'com.google.android.material:material:1.9.0'

Example MaterialButton with an icon and rounded corners:

<com.google.android.material.button.MaterialButton

android:id="@+id/materialButton"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Download"

app:icon="@drawable/ic_download"

app:iconTint="@color/white"

app:cornerRadius="8dp"

app:backgroundTint="@color/purple_500"

app:strokeColor="@color/purple_200"

app:strokeWidth="1dp"/>

To create outline button (border only) use style Widget.MaterialComponents.Button.OutlinedButton, and for text (without background) - Widget.MaterialComponents.Button.TextButton.

How to remove the ripple effect in a MaterialButton?

Add an attribute app:rippleColor="@android:color/transparent" or create a custom one ripple drawable s zero alpha transparency.

โš ๏ธ Attention: If you use MaterialButton together with a custom drawablebackground, some attributes (for example, cornerRadius) may conflict. In this case, the settings from the XML markup take precedence.

4. Custom buttons through layers (Layer-list) and selectors

For complex designs (for example, a button with a gradient, shadow and changing color when pressed) you will need to combine several drawableresources. type:

1. Selectors (selector) โ€” allow you to change the appearance of a button depending on the state (pressed, disabled, with focus). Example for a button with a color change when pressed:

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

<item android:state_pressed="true" android:color="#3700B3"/>

<item android:state_enabled="false" android:color="#CCCCCC"/>

<item android:color="#6200EE"/>

</selector>

2. Layers (layer-list) โ€” stack several drawables on top of each other. For example, to add a shadow under the button:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item>

<shape android:shape="rectangle">

<solid android:color="#33000000"/>

<corners android:radius="8dp"/>

</shape>

</item>

<item android:top="2dp" android:left="2dp">

<shape android:shape="rectangle">

<solid android:color="#6200EE"/>

<corners android:radius="8dp"/>

</shape>

</item>

</layer-list>

Apply the created layer-list to the button via android:background. For a more realistic shadow, use elevation (in Material Design) or library ShadowLayout.

โ˜‘๏ธ Testing a custom button before release

Completed: 0 / 5

5. Dynamically changing the button in the code (Kotlin/Java)

Sometimes the appearance of the button needs to be changed. programmatically - for example, when changing the theme, after loading data, or by user action. Here's how to do it on Kotlin:

Basic properties:

val button = findViewById<Button>(R.id.myButton)

button.text = "New text"

button.setTextColor(ContextCompat.getColor(this, R.color.red))

button.setBackgroundColor(ContextCompat.getColor(this, R.color.green))

For MaterialButton additional methods are available:

val materialButton = findViewById<MaterialButton>(R.id.materialButton)

materialButton.icon = ContextCompat.getDrawable(this, R.drawable.ic_check)

materialButton.iconTint = ContextCompat.getColorStateList(this, R.color.white)

materialButton.strokeColor = ContextCompat.getColorStateList(this, R.color.purple_200)

materialButton.strokeWidth = 2

Critical nuance: when dynamically changing the background through setBackgroundColor rounded corners and other settings from XML are lost. To avoid this, create several drawableresources with different colors and switch them through setBackgroundResource(R.drawable.button_red).

An example of color changing animation when when pressed:

button.setOnTouchListener { v, event ->

when (event.action) {

MotionEvent.ACTION_DOWN -> {

v.backgroundTintList = ColorStateList.valueOf(Color.parseColor("#3700B3"))

}

MotionEvent.ACTION_UP -> {

v.backgroundTintList = ColorStateList.valueOf(Color.parseColor("#6200EE"))

}

}

false

}

6. Animations and micro-interactions for buttons

Modern applications rarely do without animations. For buttons the following are relevant:

  • ๐ŸŒŠ Ripple effect (wave when pressed)
  • ๐Ÿ”„ Smooth color change
  • ๐ŸŽฏ Scaling (increase on hover)
  • โœจ Morphing (smooth shape transformation)

The simplest scaling animation via XML (res/anim/scale.xml):

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

android:interpolator="@android:anim/linear_interpolator">

<scale

android:fromXScale="1.0"

android:toXScale="0.95"

android:fromYScale="1.0"

android:toYScale="0.95"

android:pivotX="50%"

android:pivotY="50%"

android:duration="100"/>

<scale

android:startOffset="100"

android:fromXScale="0.95"

android:toXScale="1.0"

android:fromYScale="0.95"

android:toYScale="1.0"

android:pivotX="50%"

android:pivotY="50%"

android:duration="100"/>

</set>

Use animation in code:

val scaleAnim = AnimationUtils.loadAnimation(this, R.anim.scale)

button.startAnimation(scaleAnim)

For complex animations (for example, morphing into a circle) use the library Lottie or ObjectAnimator:

ObjectAnimator.ofFloat(button, "cornerRadius", 8f, 50f).apply {

duration = 300

start()

}

โš ๏ธ Attention: Excessive use of animations can lead to lags on weak devices. Test performance on devices with 1-2 GB RAM (for example, Redmi 5A or Samsung Galaxy J2).

7. Buttons in Jetpack Compose: a declarative approach

If you use Jetpack Compose, the syntax for creating buttons is radically different. Here is a basic example of a custom button:

Button(

onClick = { / action / },

colors = ButtonDefaults.buttonColors(

containerColor = Color(0xFF6200EE),

contentColor = Color.White

),

shape = RoundedCornerShape(8.dp),

modifier = Modifier

.padding(16.dp)

.height(48.dp)

) {

Text("Click me")

}

To create outline button use OutlinedButton, and for text - TextButton. Example with an icon:

Button(

onClick = { / action / },

modifier = Modifier.padding(8.dp)

) {

Icon(

imageVector = Icons.Default.Favorite,

contentDescription = "Like",

tint = Color.White

)

Spacer(Modifier.width(8.dp))

Text("Like")

}

Animations in Compose are implemented through animate*functions. For example, a smooth color change:

var isPressed by remember { mutableStateOf(false) }

val color by animateColorAsState(

targetValue = if (isPressed) Color(0xFF3700B3) else Color(0xFF6200EE)

)

Button(

onClick = { isPressed = !isPressed },

colors = ButtonDefaults.buttonColors(containerColor = color)

) {

Text("Animated button")

}

๐Ÿ’ก

Jetpack Compose allows you to create completely custom buttons without XML, but requires learning a new syntax. For existing Views projects, migrating to Compose can be costly.

FAQ: Frequently asked questions about button customization

How to make a button round?

For MaterialButton use app:cornerRadius="50%" (if height = width) or app:shapeAppearanceOverlay="@style/RoundedShape" with style:

<style name="RoundedShape">

<item name="cornerFamily">rounded</item>

<item name="cornerSize">50%</item>

</style>

For a custom button, create shape drawable s android:shape="oval".

Why does the button look different on Android 10 and Android 12?

This is due to changes in Material Design 3 (Material You), where the buttons adapt to the dynamic colors of the system. To disable this behavior, explicitly set colors via android:backgroundTint or use ?attr/colorPrimary instead of hard colors.

Is it possible to make a button with a gradient?

Yes, create one gradient drawable in res/drawable/gradient_button.xml:

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

android:shape="rectangle">

<gradient

android:startColor="#6200EE"

android:endColor="#3700B3"

android:angle="90"/>

<corners android:radius="8dp"/>

</shape>

Then apply it to the button via android:background="@drawable/gradient_button".

How to add a shadow to a button?

In Material Design use android:elevation="4dp" or app:elevation. For custom shadows, create layer-list (as in section 4) or use the library ShadowLayout:

implementation 'com.github.armcha:ShadowLayout:1.0.4'
Why doesn't it work android:drawableLeft in MaterialButton?

In MaterialButton instead drawableLeft use app:icon="@drawable/ic_my_icon" i app:iconGravity="start". For precise control over the position of the icon, create a custom one. Basic ways to change a button via XML TextView With drawableStart inside MaterialButton.