I’m new to android programming. How do I change the color of a button?
<Button
android:id="@+id/btn"
android:layout_width="55dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:text="Button Text"
android:paddingBottom="20dp"/>
asked Sep 19, 2015 at 17:10
2
The RIGHT way…
The following methods actually work.
if you wish — using a theme
By default a buttons color is android:colorAccent
. So, if you create a style like this…
<style name="Button.White" parent="ThemeOverlay.AppCompat">
<item name="colorAccent">@android:color/white</item>
</style>
You can use it like this…
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:theme="@style/Button.White"
/>
alternatively — using a tint
You can simply add android:backgroundTint
for API Level 21 and higher, or app:backgroundTint
for API Level 7 and higher.
For more information, see this blog.
The problem with the accepted answer…
If you replace the background with a color you will loose the effect of the button, and the color will be applied to the entire area of the button. It will not respect the padding, shadow, and corner radius.
answered May 2, 2019 at 14:27
4
You can change the colour two ways; through XML or through coding. I would recommend XML since it’s easier to follow for beginners.
XML:
<Button
android:background="@android:color/white"
android:textColor="@android:color/black"
/>
You can also use hex values ex.
android:background="#FFFFFF"
Coding:
//btn represents your button object
btn.setBackgroundColor(Color.WHITE);
btn.setTextColor(Color.BLACK);
answered Sep 20, 2015 at 4:25
Aicha HezitAicha Hezit
5404 silver badges5 bronze badges
4
For the text color add:
android:textColor="<hex color>"
For the background color add:
android:background="<hex color>"
From API 21 you can use:
android:backgroundTint="<hex color>"
android:backgroundTintMode="<mode>"
How to customize different buttons in Android
max pleaner
25.8k9 gold badges65 silver badges116 bronze badges
answered Sep 19, 2015 at 17:29
TomblaromTomblarom
1,3801 gold badge13 silver badges37 bronze badges
3
If the first solution doesn’t work try this:
android:backgroundTint="@android:color/white"
I hope this work.
Happy coding.
answered Apr 20, 2021 at 8:15
Pedro MolinaPedro Molina
1,01110 silver badges12 bronze badges
1
Many great methods presented above — One newer note
It appears that there was a bug in earlier versions of Material that prevented certain types of overriding the button color.
See: [Button] android:background not working #889
I am using today Material 1.3.0. I just followed the direction of KavinduDissanayake in the linked post and used this format:
app:backgroundTint="@color/purple_700"
(I changed the chosen color to my own theme of course.) This solution worked very simply for me.
answered May 25, 2021 at 3:46
Here is my code, to make different colors on button, and Linear, Constraint and Scroll Layout
First, you need to make a custom_button.xml on your drawable
- Go to res
- Expand it, right click on drawable
- New -> Drawable Resource File
- File Name : custom_button, Click OK
Custom_Button.xml Code
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/red"/> <!-- pressed -->
<item android:state_focused="true" android:drawable="@color/blue"/> <!-- focused -->
<item android:drawable="@color/black"/> <!-- default -->
</selector>
Second, go to res
- Expand values
- Double click on colors.xml
- Copy the code below
Colors.xml Code
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="black">#000</color>
<color name="violet">#9400D3</color>
<color name="indigo">#4B0082</color>
<color name="blue">#0000FF</color>
<color name="green">#00FF00</color>
<color name="yellow">#FFFF00</color>
<color name="orange">#FF7F00</color>
<color name="red">#FF0000</color>
</resources>
Screenshots below
XML Coding
Design Preview
answered Jul 29, 2018 at 4:55
Starting with API 23, you can do:
btn.setBackgroundColor(getResources().getColor(R.color.colorOffWhite));
and your colors.xml must contain:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorOffWhite">#80ffffff</color>
</resources>
answered Jan 12, 2019 at 21:01
Best way to change button color without losing button ghosting and other features.
Try it and you will see it is the best
app:backgroundTint="@color/color_name"
answered Aug 7, 2021 at 0:44
bzgdbzgd
313 bronze badges
in theme change this:
parent=»Theme.MaterialComponents.DayNight.DarkActionBar»
to that:
parent=»Theme.AppCompat.Light.NoActionBar»
It worked for me after many search
answered Jan 10, 2022 at 21:27
usually with API 21 and above :
just PUT this attribute : android:backgroundTint=» your color «
answered May 29, 2022 at 20:00
You can change the value in the XML like this:
<Button
android:background="#FFFFFF"
../>
Here, you can add any other color, from the resources or hex.
Similarly, you can also change these values form the code like this:
demoButton.setBackgroundColor(Color.WHITE);
Another easy way is to make a drawable, customize the corners and shape according to your preference and set the background color and stroke of the drawable.
For eg.
button_background.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="2dp" android:color="#ff207d94" />
<corners android:radius="5dp" />
<solid android:color="#FFFFFF" />
</shape>
And then set this shape as the background of your button.
<Button
android:background="@drawable/button_background.xml"
../>
Hope this helps, good luck!
answered Jun 24, 2020 at 10:51
see the image and easy understand
sta
28.3k8 gold badges42 silver badges55 bronze badges
answered Jul 18, 2021 at 4:17
NurulNurul
691 silver badge1 bronze badge
2
- in new update of android studio you have to change the
button -> androidx.appcompat.widget.AppCompatButton
then only the button color will changed
res/drawable/button_color_border.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#FFDA8200" />
<stroke
android:width="3dp"
android:color="#FFFF4917" />
</shape>
And add button to your XML activity layout and set background
android:background=»@drawable/button_color_border».
<androidx.appcompat.widget.AppCompatButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/button_border"
android:text="Button" />
answered Feb 10, 2022 at 11:19
SumedSumed
2972 silver badges12 bronze badges
Use below code for button background color
btn.setBackgroundResource(R.drawable.btn_rounded);
here is drawable xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle" >
<solid android:color="@color/gray_scale_color"/>
<corners android:radius="@dimen/_12sdp"/>
<stroke android:width="0.5dp"
android:color="?attr/appbackgroundColor"/>
</shape>
</item>
</layer-list>
answered Aug 8, 2022 at 5:15
i’m using api 32 and I had to do it this way in the xml code:
android:backgroundTint="@android:color/white"
answered Oct 30, 2022 at 15:39
If you are trying to set the background as some other resource file in your drawable folder, say, a custom-button.xml, then try this:
button_name.setBackgroundResource(R.drawable.custom_button_file_name);
eg. Say, you have a custom-button.xml file. Then,
button_name.setBackgroundResource(R.drawable.custom_button);
Will set the button background as the custom-button.xml file.
answered Jun 24, 2020 at 10:34
I have the same problem
the solution for me was the background color was colorPrimary of my theme
you can use custom theme as one answer say above and set the colorPrimary to what you want
1- add this to your «value/themes/themes.xml» inside resources
<resources>
<style name="Button.color" parent="ThemeOverlay.AppCompat">
<item name="colorPrimary">@color/purple_500</item>
</style>
</resources>
2- add this line to the button you want to have the color
<Button
android:theme="@style/Button.color"/>
answered Jul 20, 2021 at 13:24
1
Go to res > values > themes > theme.xml
/themes.xml
. Then change:
<style name="Theme.BirthdayGreet" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
To:
<style name="Theme.MemeShare" parent="Theme.AppCompat.Light.NoActionBar">)>
Watch this video for more information.
Jeremy Caney
6,83354 gold badges48 silver badges74 bronze badges
answered Oct 2, 2021 at 22:20
2
backgroundTint above API21 background has no effect it takes colorPrimary of the theme by default
answered Jan 28, 2022 at 9:40
tintintintin
3152 silver badges7 bronze badges
Button background color in xml
<Button
android:id="@+id/button"
android:background="#0000FF"
android:textColor="#FFFFFF"/>
Change button background color programmatically
Button button = findViewById(R.id.button);
button.setBackgroundColor(Color.BLUE);
Custom button background
shape.xml [res
—> drawble
]
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="5dp" />
<gradient
android:angle="0"
android:endColor="#0000FF"
android:startColor="#00FFFF" />
<stroke
android:width="1dp"
android:color="#000000" />
</shape>
Add this line
android:background="@drawable/shape"
full code
<Button
android:id="@+id/button"
android:background="@drawable/shape"
android:textColor="#FFFFFF"/>
Material Design Button
Change button background color
app:backgroundTint="#0000FF"
Button Stroke color
app:strokeColor="#000000"
Button Stroke width
app:strokeWidth="2dp"
Full code
<Button
android:id="@+id/button"
android:textColor="#FFFFFF"
app:backgroundTint="#0000FF"
app:strokeColor="#000000"
app:strokeWidth="2dp"/>
Hope you helpful!
answered Feb 11, 2022 at 14:53
Go to themes.xml
file under res -> values -> themes
Go to the line —
<style name="Theme.YourProjectName" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
and change it to —
<style name="Theme.YourProjectName" parent="Theme.AppCompat.DayNight.DarkActionBar">
Then proceed with changing
android:backgroundTint
to desired color
answered Dec 4, 2022 at 14:14
Payel SenapatiPayel Senapati
1,0061 gold badge10 silver badges23 bronze badges
To change the color of button programmatically
Here it is :
Button b1;
//colorAccent is the resource made in the color.xml file , you can change it.
b1.setBackgroundResource(R.color.colorAccent);
SHS
1,3944 gold badges29 silver badges42 bronze badges
answered Jun 30, 2018 at 10:14
I would like to know how to set the button color programatically?
I have coded the following but fails:
Button11.setBackgroundColor(R.color.red);
Thanks!!
asked Dec 12, 2012 at 14:59
6
R.color.red
is an ID (which is also an int
), but is not a color.
Use one of the following instead:
// If you're in an activity:
Button11.setBackgroundColor(getResources().getColor(R.color.red));
// OR, if you're not:
Button11.setBackgroundColor(Button11.getContext().getResources().getColor(R.color.red));
Or, alternatively:
Button11.setBackgroundColor(Color.RED); // From android.graphics.Color
Or, for more pro skills:
Button11.setBackgroundColor(0xFFFF0000); // 0xAARRGGBB
answered Dec 12, 2012 at 15:02
CatCat
66.4k24 gold badges133 silver badges141 bronze badges
3
Old thread, but learned something new, hope this might help someone.
If you want to change the background color but retain other styles, then below might help.
button.getBackground().setColorFilter(ContextCompat.getColor(this, R.color.colorAccent), PorterDuff.Mode.MULTIPLY);
answered Dec 14, 2015 at 6:17
sojinsojin
4,4712 gold badges36 silver badges40 bronze badges
4
The answer you’re looking for in 2020 and beyond:
setColorFilter(color, mode)
is deprecated since API 29 (as discussed here)button.setBackgroundColor(color)
messes with the button style
Now the proper way to set a buttons color is using BlendModeColorFilter()
(see documentation).
Usage:
btn.background.colorFilter = BlendModeColorFilter(color, BlendMode.MULTIPLY)
If you work with older APIs too:
fun setButtonColor(btn: Button, color: Int) {
if (Build.VERSION.SDK_INT >= 29)
btn.background.colorFilter = BlendModeColorFilter(color, BlendMode.MULTIPLY)
else
btn.background.setColorFilter(color, PorterDuff.Mode.MULTIPLY)
}
Please vote to help others finding this answer — it took me quite a while figuring this out ^^
answered May 23, 2020 at 23:46
finnmglasfinnmglas
1,4984 gold badges21 silver badges36 bronze badges
2
You can set your desired color to the button programmatically like:
Button11.setBackgroundColor(Android.Graphics.Color.parseColor("#738b28"));
Also you can give the text color for a button like:
Button11.setTextColor(Android.Graphics.Color.parseColor("#FFFFFF"));
Morse
7,5997 gold badges35 silver badges63 bronze badges
answered Oct 26, 2018 at 5:33
DeepyaDeepya
871 silver badge4 bronze badges
1
I have found that Android Studio gives me a warning that getColor()
is deprecated when trying to do this:
Button11.setBackgroundColor(getResources().getColor(R.color.red))
So I found doing the method below to be the simple, up-to-date solution:
Button11.setBackgroundColor(ContextCompat.getColor(context, R.color.red))
You want to avoid hard-coding in the color argument, as it is considered bad code style.
Edit: After using setBackgroundColor()
with my own button, I saw that the internal button padding expanded. I couldn’t find any way of changing it back to having both height and width set to «wrap_content». Maybe its a bug.
Source:
https://stackoverflow.com/a/32202256/6030520
answered Jun 10, 2018 at 4:06
JamieJamie
3873 silver badges11 bronze badges
For not changing the size of button on setting the background color:
button.getBackground().setColorFilter(button.getContext().getResources().getColor(R.color.colorAccent), PorterDuff.Mode.MULTIPLY);
this didn’t change the size of the button and works with the old android versions too.
answered Sep 12, 2018 at 18:22
SaadatSaadat
4515 silver badges9 bronze badges
Using setBackgroundColor() affects the style.
So, declare a new style of the same properties with respect to the previous button, with a a different color.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/green"/>
<corners android:radius="10dp"/>
</shape>
Now, use OnClick method.
location.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
location.setBackgroundResource(R.drawable.green);
}
});
this changes the button but looks similar to changing the background.
answered May 31, 2020 at 12:06
Further from @finnmglas, the Java answer as of 2021 is:
if (Build.VERSION.SDK_INT >= 29)
btn.getBackground().setColorFilter(new BlendModeColorFilter(color, BlendMode.MULTIPLY));
else
btn.getBackground().setColorFilter(color, PorterDuff.Mode.MULTIPLY);
answered Jan 18, 2021 at 11:38
LXJLXJ
7504 silver badges16 bronze badges
button.setBackgroundColor(getResources().getColor(R.color.red);
Sets the background color for this view.
Parameters: color the color of the background
R.color.red
is a reference generated at the compilation in gen.
Lamorak
10.9k9 gold badges45 silver badges57 bronze badges
answered Dec 12, 2012 at 15:05
zicos22zicos22
4122 silver badges8 bronze badges
You can use the below code for the button color without getting effected the style if used any
yourbtnid.background.setColorFilter(ContextCompat.getColor(context, yourcolor), PorterDuff.Mode.SRC)
Suraj Rao
29.3k11 gold badges96 silver badges103 bronze badges
answered Mar 8, 2021 at 4:46
I would like to know how to set the button color programatically?
I have coded the following but fails:
Button11.setBackgroundColor(R.color.red);
Thanks!!
asked Dec 12, 2012 at 14:59
6
R.color.red
is an ID (which is also an int
), but is not a color.
Use one of the following instead:
// If you're in an activity:
Button11.setBackgroundColor(getResources().getColor(R.color.red));
// OR, if you're not:
Button11.setBackgroundColor(Button11.getContext().getResources().getColor(R.color.red));
Or, alternatively:
Button11.setBackgroundColor(Color.RED); // From android.graphics.Color
Or, for more pro skills:
Button11.setBackgroundColor(0xFFFF0000); // 0xAARRGGBB
answered Dec 12, 2012 at 15:02
CatCat
66.4k24 gold badges133 silver badges141 bronze badges
3
Old thread, but learned something new, hope this might help someone.
If you want to change the background color but retain other styles, then below might help.
button.getBackground().setColorFilter(ContextCompat.getColor(this, R.color.colorAccent), PorterDuff.Mode.MULTIPLY);
answered Dec 14, 2015 at 6:17
sojinsojin
4,4712 gold badges36 silver badges40 bronze badges
4
The answer you’re looking for in 2020 and beyond:
setColorFilter(color, mode)
is deprecated since API 29 (as discussed here)button.setBackgroundColor(color)
messes with the button style
Now the proper way to set a buttons color is using BlendModeColorFilter()
(see documentation).
Usage:
btn.background.colorFilter = BlendModeColorFilter(color, BlendMode.MULTIPLY)
If you work with older APIs too:
fun setButtonColor(btn: Button, color: Int) {
if (Build.VERSION.SDK_INT >= 29)
btn.background.colorFilter = BlendModeColorFilter(color, BlendMode.MULTIPLY)
else
btn.background.setColorFilter(color, PorterDuff.Mode.MULTIPLY)
}
Please vote to help others finding this answer — it took me quite a while figuring this out ^^
answered May 23, 2020 at 23:46
finnmglasfinnmglas
1,4984 gold badges21 silver badges36 bronze badges
2
You can set your desired color to the button programmatically like:
Button11.setBackgroundColor(Android.Graphics.Color.parseColor("#738b28"));
Also you can give the text color for a button like:
Button11.setTextColor(Android.Graphics.Color.parseColor("#FFFFFF"));
Morse
7,5997 gold badges35 silver badges63 bronze badges
answered Oct 26, 2018 at 5:33
DeepyaDeepya
871 silver badge4 bronze badges
1
I have found that Android Studio gives me a warning that getColor()
is deprecated when trying to do this:
Button11.setBackgroundColor(getResources().getColor(R.color.red))
So I found doing the method below to be the simple, up-to-date solution:
Button11.setBackgroundColor(ContextCompat.getColor(context, R.color.red))
You want to avoid hard-coding in the color argument, as it is considered bad code style.
Edit: After using setBackgroundColor()
with my own button, I saw that the internal button padding expanded. I couldn’t find any way of changing it back to having both height and width set to «wrap_content». Maybe its a bug.
Source:
https://stackoverflow.com/a/32202256/6030520
answered Jun 10, 2018 at 4:06
JamieJamie
3873 silver badges11 bronze badges
For not changing the size of button on setting the background color:
button.getBackground().setColorFilter(button.getContext().getResources().getColor(R.color.colorAccent), PorterDuff.Mode.MULTIPLY);
this didn’t change the size of the button and works with the old android versions too.
answered Sep 12, 2018 at 18:22
SaadatSaadat
4515 silver badges9 bronze badges
Using setBackgroundColor() affects the style.
So, declare a new style of the same properties with respect to the previous button, with a a different color.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/green"/>
<corners android:radius="10dp"/>
</shape>
Now, use OnClick method.
location.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
location.setBackgroundResource(R.drawable.green);
}
});
this changes the button but looks similar to changing the background.
answered May 31, 2020 at 12:06
Further from @finnmglas, the Java answer as of 2021 is:
if (Build.VERSION.SDK_INT >= 29)
btn.getBackground().setColorFilter(new BlendModeColorFilter(color, BlendMode.MULTIPLY));
else
btn.getBackground().setColorFilter(color, PorterDuff.Mode.MULTIPLY);
answered Jan 18, 2021 at 11:38
LXJLXJ
7504 silver badges16 bronze badges
button.setBackgroundColor(getResources().getColor(R.color.red);
Sets the background color for this view.
Parameters: color the color of the background
R.color.red
is a reference generated at the compilation in gen.
Lamorak
10.9k9 gold badges45 silver badges57 bronze badges
answered Dec 12, 2012 at 15:05
zicos22zicos22
4122 silver badges8 bronze badges
You can use the below code for the button color without getting effected the style if used any
yourbtnid.background.setColorFilter(ContextCompat.getColor(context, yourcolor), PorterDuff.Mode.SRC)
Suraj Rao
29.3k11 gold badges96 silver badges103 bronze badges
answered Mar 8, 2021 at 4:46
Post Views: 99 430
Одним из важных компонентов пользовательского интерфейса в приложения является кнопка. Она используется для выполнения различных действий пользователя.
В этой статье мы приведём примеры использования и стилизации кнопки.
Добавляем кнопку на разметку
Пользовательский интерфейс приложения определён в XML-файле с разметкой. Вы можете добавить элемент Button и установить атрибуты вручную. Или вы можете, воспользовавшись инструментом дизайна, добавить Button из палитры элементов и задать атрибуты.
<Button android:id="@+id/account_b" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:text="Добавить аккаунт" />
Атрибуты кнопки
Button является подклассом TextView и наследует атрибуты от TextView и View. Ниже приведены некоторые важные атрибуты кнопки, которые можно использовать для настройки стиля и поведения.
- background: установка в качестве фона как цвета, так и drawable
- onClick: установить метод, который будет запускаться при нажатии на кнопку
- minHeight: для определения минимальной высоты кнопки
- minWidth: для определения минимальной ширины кнопки
- stateListAnimator: определение анимации при изменении состояния кнопки
- focusable: для определения того, будет ли обработано нажатие клавиши
- clickable: указать, является ли кнопка кликабельной
- gravity: установка выравнивания текста кнопки
- textAppearance: установить стиль текста
Включение и выключение кнопки
Вы можете использовать атрибут enabled для включения или выключения кнопки, установив его в true или false. Также это можно сделать программно, вызвав метод setEnabled(), как показано ниже:
((Button)findViewById(R.id.button)).setEnabled(false);
Кнопка с Drawable
Вы можете отображать на кнопке вместе с текстом изображение, используя drawableTop, drawableRight, drawableBottom или drawableLeft, в зависимости от того, где располагать картинку, как показано на скриншоте ниже.
ImageButton
Android также предоставляет ImageButton, задачей которого является использование изображения в качестве кнопки. Чтобы установить изображение, вы можете использовать атрибут src. Вы также можете использовать разные изображения, которые будут меняться в зависимости от состояния кнопки, меняя в XML drawable selector как показано ниже.
<ImageButton android:id="@+id/img_b" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="doSomething" android:src="@drawable/img_state" />
Пример XML drawable selector
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/arrow_down" android:state_pressed="true"/> <item android:drawable="@drawable/arrow_up" android:state_focused="true"/> <item android:drawable="@drawable/arrow_up"/> </selector>
Обработка нажатий на кнопку
Клики можно обрабатывать двумя способами. Первый — это установить атрибут onClick в разметке XML. Второй — назначить кнопке слушатель в коде активности или фрагмента.
Чтобы установить атрибут onClick, сначала определите метод типа void, принимающий в качестве параметра View, в активности или фрагменте и затем используйте имя этого метода как значение для атрибута onClick, как показано ниже.
public void doSomething(View v) { //do something }
<Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="doSomething" android:text="Делай что-нибудь" />
Ниже приведён код обработки нажатия с помощью слушателя.
Button doSomethingButton = (Button) findViewById(R.id.do_something_b); doSomethingButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //пишем код } });
Дизайн и стили кнопок
Вы можете применять стили и темы для изменения внешнего вида кнопок. Платформа Android предоставляет заранее определённые стили. На рисунке ниже вы можете увидеть, как отображаются кнопки с различными стилями.
Пример применения темы для кнопки.
<Button android:id="@+id/button3" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Button3" style="@style/Widget.AppCompat.Button.Borderless.Colored" />
Настройка стилей кнопок
Вы можете изменить цвета по умолчанию для стилей, применяемых к кнопке, установив атрибут colorAccent на уровне приложения и атрибут colorButtonNormal на уровне виджета для нужных цветов. Атрибут colorControlHighlight используется для установки цвета кнопки, когда она находится в нажатом состоянии.
Как только вы определите собственный стиль, вы можете применить его к кнопкам с помощью атрибута theme. Ниже приведен пример пользовательской темы.
<style name="PurpleButton" parent="@style/Widget.AppCompat.Button.Colored"> <item name="colorButtonNormal">#1a237e</item> <item name="colorControlHighlight">#673ab7</item> </style>
Кнопка с закруглёнными углами
Вы можете определить элемент inset, как показано ниже, чтобы создать кнопку с закруглёнными углами и сохранить файл с drawable в папке res/drawable. Вы можете увеличить или уменьшить атрибут радиуса элемента, чтобы отрегулировать радиус углов кнопки.
<?xml version="1.0" encoding="utf-8"?> <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetBottom="6dp" android:insetLeft="4dp" android:insetRight="4dp" android:insetTop="6dp"> <ripple android:color="?attr/colorControlHighlight"> <item> <shape android:shape="rectangle" android:tint="#0091ea"> <corners android:radius="10dp"/> <solid android:color="#1a237e"/> <padding android:bottom="6dp"/> </shape> </item> </ripple> </inset>
Затем определите стиль, задающий атрибут background для xml drawable и примените его к кнопке с помощью атрибута style.
<style name="RoundedCornerButton" parent="@style/Widget.AppCompat.Button.Colored"> <item name="background">@drawable/btn_rounded_corner</item> <item name="colorButtonNormal">#1a237e</item> <item name="colorControlHighlight">#673ab7</item> </style>
Высота и тень кнопки
Вы можете установить атрибуты elevation и translationZ, чтобы нарисовать тень кнопки.
<Button ... android:elevation="6dp" android:stateListAnimator="@null" android:translationZ="4dp"/>
Настройка анимации тени
Вы можете определить различные свойства теней для разных состояний кнопки и анимировать переход путём определения селектора. Вы можете применить аниматор к кнопке, используя свойство stateListAnimator.
Обратите внимание, что stateListAnimator установлен в null в приведённом выше примере. Это было сделано для удаления аниматора по умолчанию, чтобы elevation и translationZ работали.
Чтобы настроить анимацию тени при изменении состояния кнопок, вам нужно определить селектор, как показано ниже, в папке res/animator и установить свойство stateListAnimator своей темы для определённого аниматора.
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="true" android:state_pressed="true"> <set> <objectAnimator android:duration="120" android:propertyName="translationZ" android:valueTo="8dp" android:valueType="floatType"/> <objectAnimator android:duration="120" android:propertyName="elevation" android:valueTo="4dp" android:valueType="floatType"/> </set> </item> <item android:state_enabled="true"> <set> <objectAnimator android:duration="120" android:propertyName="translationZ" android:startDelay="80" android:valueTo="4dp" android:valueType="floatType"/> <objectAnimator android:duration="120" android:propertyName="elevation" android:valueTo="2dp" android:valueType="floatType"/> </set> </item> </selector>
Примените следующую тему, которая использует аниматор, к кнопке с использованием атрибута style или theme.
<style name="CustomAnimationButton" parent="@style/Widget.AppCompat.Button"> <item name="colorButtonNormal">#1a237e</item> <item name="colorControlHighlight">#673ab7</item> <item name="android:stateListAnimator">@animator/button_elevation</item> </style>
Простая кнопка логина
Совмещая всё вышесказанное, можно создать красивую кнопку, позволяющую, например, заходить пользователям на свои аккаунты. Код разметки будет выглядеть следующим образом:
<Button android:id="@+id/btn_email_password" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="4dp" android:background="@drawable/element_background" android:drawablePadding="8dp" android:fontFamily="sans-serif-medium" android:paddingLeft="8dp" android:paddingRight="8dp" android:text="Password" android:textAllCaps="false" android:textStyle="normal" />
Стиль фона:
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="rectangle"> <solid android:color="#BDBDBD"/> <corners android:radius="5dp"/> </shape> </item> <item android:bottom="2dp" android:left="0dp" android:right="0dp" android:top="0dp"> <shape android:shape="rectangle"> <solid android:color="#ffffff"/> </shape> </item> </layer-list>
Кроме того, с помощью атрибута drawableLeft можно добавить изображение к нашей кнопке, в том числе и векторное. На старых устройствах, векторные изображения вызывают падение всего приложения, поэтому сделаем это программно в коде активности при помощи AppCompatResources:
((Button) findViewById(R.id.btn_email_password)).setCompoundDrawablesWithIntrinsicBounds( AppCompatResources.getDrawable(this, R.drawable.ic_vpn_key_black_24dp), null, null, null);
Метод setCompoundDrawablesWithIntrinsicBounds() делает то же, что и атрибуты drawableLeft, drawableTop и так далее. В качестве параметров нужно указать, где именно будет размещаться изображение (указываем null в случае, если здесь изображение не нужно).
ColorStateList is an object which can define in an XML file that can be used to apply different colors on widgets (such as Buttons, etc) depending on the state of Widgets to which it is being applied. For Example, There are many states of Buttons like (pressed, focussed, or none of them ) and other widgets states like enable, checkable, checked, etc, Using Color State List is a nice way to change the color of the button without using shape drawables or custom images. One should remember the color state list can be used anywhere, where color is used. The color state list is defined in XML and saved under the res/color folder. The root element of the color state list is a selector and the item element is defined for each state that you want to define the color by using color and alpha attributes. The default color should be the last element which is used when color for a specific state is not defined. A sample GIF is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Kotlin language.
Approach
Step 1: Create a New Project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language.
Step 2: Working with the activity_main.xml file
Go to the layout folder and in the activity_main.xml file change the ConstraintLayout to LinearLayout and give its orientation vertical. Add the Button and Switch to the layout. Below is the code for the activity_main.xml file.
XML
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
LinearLayout
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:gravity
=
"center"
android:orientation
=
"vertical"
tools:context
=
".MainActivity"
>
<
Button
android:id
=
"@+id/button"
android:layout_width
=
"160dp"
android:layout_height
=
"110dp"
android:backgroundTint
=
"@color/button_background_color"
android:text
=
"Click Me"
android:textColor
=
"@color/button_text_color"
android:textSize
=
"24sp"
android:textStyle
=
"bold"
/>
<
Switch
android:id
=
"@+id/buttonSwitch"
android:layout_width
=
"160dp"
android:layout_height
=
"80dp"
android:checked
=
"true"
android:text
=
"Enabled"
android:textAlignment
=
"center"
android:textSize
=
"24sp"
android:textStyle
=
"bold"
/>
</
LinearLayout
>
Step 3: Add a resource directory named as the color
Add a resource directory named as color to the res folder and keep the root element as a selector, since we want to select the color on the basis of the state. Add two resource files named as button_text_color.xml and button_background_color.xml to the color resource directory. Keep the selector as the root element for the same reason as mentioned above. For performing the above things refer to the below images and codes.
In order to create the color resource file, do right click on the res folder, click on New and select Android Resource Directory.
Now create both the resource file (button_text_color.xml and button_background_color.xml) within the color resource directory by doing right-click on the color directory and keeping the selector as the root element.
Below is the code for the button_background_color.xml file.
XML
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
item
android:state_enabled
=
"false"
android:color
=
"#b6b7b5"
/>
<
item
android:state_pressed
=
"true"
android:color
=
"#22a540"
/>
<
item
android:state_selected
=
"true"
android:color
=
"#fabcff"
/>
<
item
android:color
=
"@android:color/white"
/>
</
selector
>
Below is the code for the button_text_color.xml file.
XML
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
item
android:state_enabled
=
"false"
android:color
=
"@android:color/white"
/>
<
item
android:state_selected
=
"true"
android:color
=
"@android:color/white"
/>
<
item
android:color
=
"#db402c"
/>
</
selector
>
Step 4: Working with the MainActivity.kt file
Go to the MainActivity.kt file, and refer to the following code. Below is the code for the MainActivity.kt file. Comments are added inside the code to understand the code in more detail.
Kotlin
import
android.os.Bundle
import
androidx.appcompat.app.AppCompatActivity
import
kotlinx.android.synthetic.main.activity_main.*
class
MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super
.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
button.isSelected != button.isSelected
}
buttonSwitch.setOnCheckedChangeListener { buttonView, isChecked ->
button.isEnabled = isChecked
}
}
}
Output: Run on Emulator
Время прочтения
18 мин
Просмотры 224K
Приветствую, уважаемое сообщество.
В своем цикле статей по разработке Android-приложений я хочу поделиться с вами интересными и полезными приемами верстки сложных элементов управления. Мы рассмотрим как базовые приемы верстки, так и продвинутые способы ее оптимизации, которые существенно облегчают развитие и сопровождение Android-приложений, экономят время и деньги.
Первая часть предназначена для начинающих разработчиков. Я покажу, как сделать достаточно сложную кнопку исключительно версткой, не применяя Java-кода, ни тем более собственных компонентов. Знание этих приемов верстки пригодится и при работе с другими компонентами Android. По ходу статьи я буду подробно пояснять, что означают те или иные константы, атрибуты, команды и тому подобное. Но я также буду давать ссылки на официальную документацию Google, где вы можете подробно изучить каждую тему. Данная статья обзорная, я не ставлю цели привести здесь всю документацию, переведенную на русский язык. Поэтому я рекомендую изучать официальные источники, в частности те статьи, ссылки на которые я привожу здесь.
Что мы хотим сделать в данной статье? Допустим, мы делаем приложение, позволяющее включать/выключать функцию телефонии на смартфоне, в приложении будет кнопка “вкл/выкл”. Мы создадим кнопку с нашим собственным фоном и рамкой со скругленными углами. Фон и рамка будут меняться, когда кнопка получает фокус или становится нажатой. У кнопки будет текстовое название и иконка, поясняющая назначение кнопки визуально. Цвет текста и иконки также будет меняться при нажатии. Что еще? Так как кнопки “вкл./выкл.” встречаются в приложениях довольно часто, в Android уже есть готовый функционал для хранения/изменения состояния. Мы будем использовать его вместо того, чтобы изобретать собственный велосипед. Но отображение этого состояния мы сделаем свое, чтобы оно подходило нам по стилю.
Выглядеть это будет примерно так:
По левому краю кнопки располагаем иконку. Текст кнопки выравниваем по вертикали по центру, а по горизонтали левому краю. Но при этом текст не должен оказаться поверх иконки. По правому краю кнопки выравниваем индикатор включенного или выключенного телефона. Пространство между текстом на кнопке и правой иконкой индикатора “тянется” при необходимости. При нажатии кнопки фон становится серым, а рамка и все элементы на кнопке становятся белыми.
Делать все это будем только версткой. Почему верстка, а не код? Правильно сверстанная страница может легко стилизоваться, то есть ее можно менять практически до неузнаваемости простой заменой стиля. Можно даже предлагать пользователю выбирать тот стиль, который ему больше по душе. Стили в Android — это аналог каскадных таблиц CSS в HTML.
Решения, выполненные версткой, обычно компактнее аналогичных решений, выполненных кодом, при этом меньше шансов допустить ошибку. И большинство сверстанных без применения кода страниц можно просматривать и отлаживать в режиме дизайн (то есть прямо в IDE), для этого не нужно запускать приложение, ожидать деплоя и т.п.
Создаем каркас приложения
Приступим к реализации. Для демонстрации я буду использовать Android Developer Tools (ADT), построенный на Eclipse.
Создадим новый проект. File->New->Android Application Project.
Application Name: MysteriesOfButtonsPart1
Project Name: MysteriesOfButtonsPart1
Package Name: com.mysteriesofbuttons.part1
Остальные параметры оставим по умолчанию:
Next. На следующей странице для экономии времени позволим ADT создать для нас тестовую Activity:
Next. Иконки оставим по умолчанию, в данном случае речь не о них.
Next. Создаем пустую Activity, то есть опять же все по умолчанию:
Next. Имя Activity оставляем без измений:
Finish. Наконец-то можем перейти к делу.
Простейшая кнопка
Начнем с кода Layout. Откроем файл /res/layout/activity_main.xml
и заменим все его содержимое следующим кодом:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Телефония" />
</RelativeLayout>
RelativeLayout
— макет, в котором дочерние элементы размещаются относительно друг друга, например, расположить кнопку слева от другой кнопки и т.п. Подробнее о работе RelativeLayout
можно почитать здесь.
Button
— наша кнопка. Мы задаем ей атрибут android:id
, по которому сможем идентифицировать ее в приложении. Формат @+id/
означает, что в ресурсах должен быть создан новый идентификатор. Если бы мы указали @id/
, то это бы означало, что в ресурсах указанный идентификатор уже должен быть.
А вот так мы задаем отображаемый пользователю текст: android:text="Телефония"
Забегая вперед, скажу, что весь текст, который видит пользователь, должен храниться не в коде макетов страниц и не в Java-коде, а в ресурсах strings.xml
, чтобы приложение могло поддерживать более одного языка, но об этом подробнее в следующей части. Пока что мы укажем текст прямо в макете, чтобы улучшить наглядность примера.
Как RelativeLayout
, так и Button
имеют атрибуты android:layout_width
и android:layout_height
. Это обязательные атрибуты любого View
. Как следует из названия, они обозначают соответственно ширину и высоту элементов. Их можно задавать в различных единицах, но мы не используем конкретные размеры, как вы могли заметить. Мы используем константы match_parent
и wrap_content
.
match_parent
означает, что элемент должен полностью заполнить своего родителя по горизонтали либо по вертикали, в зависимости от того, задаем ли мы ширину или высоту.
wrap_content
означает, что размер элемента должен быть минимальным, но таким, чтобы все содержимое элемента в него поместилось.
Есть еще константа fill_parent
, которая означает ровно то же самое, что и match_parent
. Зачем использовать две одинаковых константы? fill_parent
был введен до версии API 8, а с восьмой версии является устаревшим и не рекомендуется к использованию. Дело в том, что для англоязычных разработчиков match_parent
точнее отражает смысл константы, чем fill_parent
.
Я стараюсь использовать эти константы match_parent
и wrap_content
везде, где только возможно, всячески избегая указания фиксированных размеров, так как приложения Android работают на устройствах с сильно отличающимися размерами экранов.
Теперь, когда с основой окна разобрались, давайте перейдем к коду нашей Activity MainActivity.java
:
package com.mysteriesofbuttons.part1;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
В этом коде мы видим только одну имеющую смысл команду: setContentView(R.layout.activity_main);
Этот метод устанавливает ресурс макета страницы, с которым будет работать Activity.
Давайте запустим наше приложение и посмотрим, что получилось:
А теперь откроем в Eclipse файл activity_main.xml
и нажмем кнопку Graphical Layout
:
Мы видим ту же кнопку с теми же размерами, в тех же цветах, что и на эмуляторе. Только чтобы это увидеть, нам не пришлось ждать запуска эмулятора и деплоя приложения. Сохранили время? Первый профит от верстки. В дальнейшем будем стараться обходиться без эмулятора, тестируя на нем не каждый шаг, а только готовую версию.
Стили текста
Теперь займемся выравниванием. Сейчас текст на кнопке выровнен по центру. Это стиль по умолчанию для кнопки. Но нам нужно выровнять текст по левому краю, сохранив выравнивание по центру по вертикали. Как это сделать? Добавим к кнопке атрибут android:gravity
:
<Button
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Телефония"
android:gravity="left|center_vertical" />
Этот атрибут может принимать одно или два значения, в нашем случае два. Значения разделяются вертикальной чертой |
Как это выглядит:
О различных вариантах выравнивания и о том, что они означают, можно подробно почитать здесь
Попробуйте “поиграть” с этими вариантами и посмотреть, как это влияет на внешний вид кнопки. Если хотите сделать текст на кнопке жирным и/или курсивом, воспользуйтесь параметром android:textStyle
, например android:textStyle="bold|italic"
. Если нужно изменить размер текста на кнопке, подойдет параметр android:textSize
, например: android:textSize="24sp"
.
sp
— Scale-independent Pixels — единица измерения, основанная на плотности экрана и на настройках размера шрифта. Чтобы текст выглядел одинаково хорошо на разных экранах, рекомендуется задавать его размер именно в sp
.
Зададим эти параметры нашей кнопке:
<Button
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Телефония"
android:gravity="left|center_vertical"
android:textStyle="bold|italic"
android:textSize="24sp" />
Я предпочитаю оставлять стили ближе к значениям по умолчанию, так как они тщательно подбирались высоко оплачиваемыми дизайнерами, и с моим чувством вкуса я очень сомневаюсь, что смогу сделать лучше. Данный пример призван показать читателю как можно больше возможностей, и не претендует на звание произведения искусства, поэтому прошу не пинать за то, что раньше оно выглядело лучше.
Помещаем иконку на кнопку
Идем дальше. Теперь нам нужно добавить иконку на кнопку. Иконка задается следующим файлом icon_phone_normal.png
:
кликните, чтобы скачать
Импортируем его в ресурсы приложения в каталог drawable-hdpi
. Чтобы задать иконку кнопке, добавим ей атрибут android:drawableLeft
:
<Button
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Телефония"
android:gravity="left|center_vertical"
android:textStyle="bold|italic"
android:textSize="24sp"
android:drawableLeft="@drawable/icon_phone_normal" />
Кроме android:drawableLeft
, есть еще несколько атрибутов, которые позволяют задавать иконки, размещая их в других частях кнопки: android:drawableTop
, android:drawableBottom
, android:drawableRight
, android:drawableStart
, android:drawableEnd
.
Как вы заметили, мы указали путь к иконке без расширения PNG
, а также без суффикса -hdpi
. Это не опечатка. Расширение никогда не указывается, так как в имени идентификатора не может быть точки. А суффикс -hdpi
будет подставлен Android автоматически, так как это единственный каталог drawable
, в котором есть иконка icon_phone_normal
. Если бы иконка была не только в каталоге drawable-hdpi
, но и в drawable-mdpi
, к примеру, то Android выбрал бы наиболее полходящую для разрешения экрана того устройства, на котором запущено приложение. Так вы можете поставлять качественные продукты, одинаково хорошо выглядящие на устройствах с разным размером и плотностью экрана. О поддержке разных экранов у Google есть очень хорошая статья.
Собственный фон для кнопки
Теперь, когда мы разобрались с drawable-ресурсами, давайте заменим фон нашей кнопки на тот, который нам нужен. Для этого мы будем использовать такую картинку button_normal.png
:
кликните, чтобы скачать
Импортируйте ее в drawable-hdpi
. На картинке мы видим черные полоски вдоль каждой из границ экрана. Они служат для того, чтобы Android правильно растягивал картинку под нужный нам размер. Левая и верхняя линии показывают, какая область картинки будет растягиваться по вертикали и горизонтали соответственно. А правая и нижняя линии показывают, в какую область растянутой картинки нужно вписывать содержимое элемента, если у него есть дочерние элементы. При этом сами черные линии конечно же не видны на результирующей картинке.
Это называется nine-patch drawable, об этой технике верстки подробно можно почитать здесь
Чтобы ресурс считался 9-patch, в его имени перед расширением должна присутствовать девятка, отделенная от остального имени еще одной точкой, как у нас: button_normal.9.png
Как назначить элементу такой растягиваемый фон? Откроем текст нашей кнопки и добавим ей атрибут android:background
:
<Button
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Телефония"
android:gravity="left|center_vertical"
android:textStyle="bold|italic"
android:textSize="24sp"
android:drawableLeft="@drawable/icon_phone_normal"
android:background="@drawable/button_normal" />
Выглядит не очень красиво, так как кнопка “прижалась” к сторонам экрана вплотную. Это случилось потому, что в фоне по умолчанию, который мы сменили на наш собственный, рамка кнопки была нарисована с отступом, и этот отступ мы видели на предыдущих скриншотах. Мы также можем перерисовать фон кнопки, но можем задать отступ и другим способом, и хорошо бы сразу для всех элементов окна, чтобы не дублировать код для каждого. Для этого подойдет атрибут android:padding
у тега RelativeLayout
:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="6dp" >
Что такое dp
? Density-independent pixel — мера, которая будет автоматически масштабироваться на устройствах с разной плотностью пикселей экрана так, чтобы элемент выглядел одинаково. Всегда используйте dp
, а не px
, когда необходимо задать конкретный размер, иначе приложение будет выглядеть хорошо только на вашем телефоне.
Атрибут android:padding
задает одинаковые отступы со всех сторон. Если мы хотим задать разные отступы с каждой стороны отдельно, можем использовать атрибуты android:paddingLeft
, android:paddingRight
, android:paddingTop
, android:paddingBottom
, android:paddingStart
и android:paddingEnd
.
Рассмотренные нами до сих пор атрибуты есть не только у кнопки, но и у других элементов. Например, android:background
есть у всех видимых элементов, android:drawableLeft
— у TextEdit
и так далее.
Идем дальше. Если запустить наше приложение, мы увидим, что при щелчке на кнопку ее внешний вид никак не меняется, то есть визуально не видно, нажата кнопка или нет. В таком виде оставлять нашу кнопку нельзя, так как пользователь не сможет понять, работает приложение, или нет.
Работаем с состояниями в Android
Здесь нам на помощь приходят состояния. Когда с кнопкой ничего не происходит, она находится в не нажатом состоянии. Если на кнопке находится фокус ввода, она переходит в состояние state_focused
. Если нажать на кнопку пальцем, она будет находиться в состоянии state_pressed
, пока мы не отпустим палец. Как это нам поможет? Мы можем задавать внешний вид элементов для каждого состояния отдельно. Дальше мы детально рассмотрим, как это делается. Обратите внимание, что состояние можно использовать для отрисовки всего, что видно пользователю: иконки, картинки, отдельные цвета и т.п.
Начнем с фона. Зададим для нашей кнопки красную рамку, когда она в фокусе, и рамку с инвертированными цветами, когда она нажата. Для этого импортируйте в каталог drawable-hdpi
следующие изображения:
кликните, чтобы скачать
кликните, чтобы скачать
Теперь у нас есть 3 картинки фона на 3 состояния. Но атрибут android:background
можно задать только один раз. Чтобы выйти из ситуации, мы создадим новый drawable-ресурс selector
, объединяющий наши 3 картинки.
Щелкнем правой кнопкой мыши на каталоге drawable-hdpi
, выберем New->Android XML File. Введем название файла button_background
и выберем корневой элемент selector
:
Finish.
Мы получили заготовку следующего содержания:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
</selector>
Добавим в селектор картинки для состояния state_focused
и state_pressed
:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/button_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/button_focused" android:state_focused="true" />
<item android:drawable="@drawable/button_normal" />
</selector>
Обратите внимание, что для картинки button_normal
состояние не указывается. Это означает, что такая картинка будет использована всегда, если кнопка не в состоянии state_focused
или state_pressed
. Кроме рассмотренных состояний можно использовать еще несколько, полный перечень описан здесь
Как работает селектор? Когда селектор назначен какому-то элементу, он постоянно получает состояние элемента-хозяина, и возвращает ему первый из перечисленных ресурсов, который соответствует состоянию владельца.
Откроем текст нашего макета activity_main.xml
и заменим фон кнопки на button_background
:
<Button
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Телефония"
android:gravity="left|center_vertical"
android:textStyle="bold|italic"
android:textSize="24sp"
android:drawableLeft="@drawable/icon_phone_normal"
android:background="@drawable/button_background" />
Также затемним фон всего окна, чтобы лучше видеть белую рамку нажатой кнопки:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="6dp"
android:background="#dddddd" >
Теперь, если запустить приложение на эмуляторе, и нажать кнопку, мы увидим, что она меняет свой фон:
Изменяем иконку при нажатии
Уже неплохо, но можно и лучше. Давайте повторим процесс создания селектора для смены иконки телефона в нажатом состоянии. Импортируйте в drawable-hdpi
иконку icon_phone_pressed.png
:
кликните, чтобы скачать
Создайте селектор icon_phone
со следующим текстом:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/icon_phone_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/icon_phone_normal" />
</selector>
И в тексте кнопки замените drawableLeft
на наш новый селектор icon_phone
:
<Button
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/button_background"
android:drawableLeft="@drawable/icon_phone"
android:gravity="left|center_vertical"
android:text="Телефония"
android:textSize="24sp"
android:textStyle="bold|italic" />
Изменяем цвет текста при нажатии
Теперь иконка меняется при нажатии на кнопку так же, как и фон. Осталось разобраться с цветом текста. Он пока что остается черным в любом состоянии. Если бы в нажатом виде текст тоже становился белым, как рамка и иконка, кнопка выглядела бы куда интереснее.
Управление цветом несколько отличается от картинок. Пойдем по порядку. Во-первых, цвета хранятся в отдельном каталоге, который мы должны создать. Добавим подкаталог color
в каталоге res
, на одном уровне с каталогом drawable-hdpi
:
Далее в каталоге color
создадим Android XML File с именем text_color
и корневым элементом selector
:
И заменим его содержимое следующим:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/white" android:state_pressed="true" />
<item android:color="#484848" />
</selector>
По аналогии с картинками, здесь задаются цвета для состояния state_pressed
и состояния по умолчанию. Цвета здесь задаются двумя способами: android:color="@android:color/white"
и android:color="#484848"
В первом случае мы используем заранее созданный цвет в пространстве имен android
. Во втором — указываем RGB-значение цвета в шестнадцатиричной системе исчисления. В данном случае мы задали цвет по умолчанию такой же, как цвет рамки в ненажатом виде.
Теперь вернемся к исходнику нашей кнопки и пропишем цвет текста android:textColor="@color/text_color"
:
<Button
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/button_background"
android:drawableLeft="@drawable/icon_phone"
android:gravity="left|center_vertical"
android:text="Телефония"
android:textSize="24sp"
android:textStyle="bold|italic"
android:textColor="@color/text_color" />
Теперь мы не можем видеть результат в Graphical Layout, это известная проблема плагина, которую, я надеюсь, Google когда-нибудь починит. К сожалению, тестировать цвета с состоянием можно только на эмуляторе или реальном устройстве.
На этом художественная часть верстки завершена. Сейчас кнопка выглядит так:
Прикручиваем ToggleButton
Далее поговорим о том, как отображать состояние телефонии на кнопке (вкл/выкл). Мы помним, что у кнопки иконка может быть не только слева. Для отображения текущего состояния мы добавим кнопке иконку справа. Пусть это будет галочка для состояния Вкл и крестик для состояния Выкл. Как мы будем менять иконки? Самый очевидный вариант — это определить обработчик события OnClickListener
и поочередно менять иконку drawableRight
. Вполне рабочий вариант. Но что делать, если на странице не одна, а 10 кнопок, и вообще кнопка может быть не только на этой странице. Тогда наш путь приведет к дублированию кода, который будет копипастом кочевать из одной Activity в другую, не самое красивое решение. Да и если нужно будет что-то изменить, менять придется во многих местах. Хотелось бы этого избежать.
К счастью, Android предоставляет для этих целей специальный компонент — ToggleButton
. Эта кнопка может находиться в двух состояниях: включено и выключено. Заменим в нашем макете тег Button
на ToggleButton
:
<ToggleButton
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/button_background"
android:drawableLeft="@drawable/icon_phone"
android:gravity="left|center_vertical"
android:text="Телефония"
android:textSize="24sp"
android:textStyle="bold|italic"
android:textColor="@color/text_color" />
Так как ToggleButton
наследуется от Button
, к ней применимы все атрибуты Button
, но есть нюанс. ToggleButton
игнорирует атрибут text
, зато вводит два новых: textOn
и textOff
. Они задают текст для включенного и выключенного состояний соответственно. Но мы хотим отображать состояние картинкой, а текст хотим оставить как есть. Поэтому пропишем наш текст обоим атрибутам, а атрибут text
уберем за ненадобностью:
<ToggleButton
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/button_background"
android:drawableLeft="@drawable/icon_phone"
android:gravity="left|center_vertical"
android:textOn="Телефония"
android:textOff="Телефония"
android:textSize="24sp"
android:textStyle="bold|italic"
android:textColor="@color/text_color" />
Теперь подготовим картинки для отображения состояния кнопки. Импортируйте в drawable-hdpi
ресурсы icon_on_normal.png
, icon_on_pressed.png
, icon_off_normal.png
и icon_off_pressed.png
(представлены в порядке перечисления):
кликните, чтобы скачать
кликните, чтобы скачать
кликните, чтобы скачать
кликните, чтобы скачать
Внимание: белые иконки на прозрачном фоне не очень здорово видны в браузере на белом фоне.
Зачем четыре иконки? Вспомним, что мы хотим отображать все элементы кнопки белыми, когда пользователь удерживает кнопку нажатой. Поэтому для каждого состояния Вкл и Выкл мы должны дать по две иконки: в нажатом и отпущенном состоянии. Итого четыре.
Создадим новый drawable
селектор с именем icon_on_off
:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@drawable/icon_on_pressed"
android:state_checked="true"
android:state_pressed="true" />
<item
android:drawable="@drawable/icon_on_normal"
android:state_checked="true" />
<item
android:drawable="@drawable/icon_off_pressed"
android:state_checked="false"
android:state_pressed="true" />
<item
android:drawable="@drawable/icon_off_normal"
android:state_checked="false" />
</selector>
Здесь видно, что компонент может иметь сразу несколько состояний, например он может быть одновременно отмеченным и нажатым, или отмеченным и ненажатым и так далее.
android:state_checked="true"
соответствует кнопке в режиме Вкл, а android:state_checked="false"
— кнопке в режиме Выкл.
Теперь вернемся к нашей кнопке и добавим ей атрибут android:drawableRight="@drawable/icon_on_off"
. Для наглядности я добавил его сразу после android:drawableLeft
:
<ToggleButton
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/button_background"
android:drawableLeft="@drawable/icon_phone"
android:drawableRight="@drawable/icon_on_off"
android:gravity="left|center_vertical"
android:textOn="Телефония"
android:textOff="Телефония"
android:textSize="24sp"
android:textStyle="bold|italic"
android:textColor="@color/text_color" />
Что у нас получится, если запустить приложение? Мы видим кнопку ненажатую, в режиме Выключено. При этом если ее нажать и держать, все элементы отображаются белым на сером фоне:
Отпускаем кнопку, состояние меняется на Включено. Если нажать еще раз, снова увидим серый фон и белые иконки, после чего состояние опять будет Выключено:
Именно то, что нам нужно.
Немного кода
На всякий случай давайте посмотрим, как можно в коде нашего приложения понять, включена кнопка или выключена. Для этого мы можем анализировать значение isChecked()
кнопки: true
— включена, false
— выключена. Добавим атрибут android:onClick="onToggleButtonClick"
к нашей кнопке:
<ToggleButton
android:id="@+id/act_main_btn_telephony"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/button_background"
android:drawableLeft="@drawable/icon_phone"
android:drawableRight="@drawable/icon_on_off"
android:gravity="left|center_vertical"
android:textOn="Телефония"
android:textOff="Телефония"
android:textSize="24sp"
android:textStyle="bold|italic"
android:textColor="@color/text_color"
android:onClick="onToggleButtonClick" />
В MainActivity.java
добавим соответствующий метод:
package com.mysteriesofbuttons.part1;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import android.widget.ToggleButton;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onToggleButtonClick(View button) {
Toast.makeText(
getApplicationContext(),
Boolean.toString(((ToggleButton) button).isChecked()),
Toast.LENGTH_SHORT).show();
}
}
Запустив приложение и нажав кнопку, мы увидим внизу экрана текстовые подсказки true
/false
. А это значит, что все работает.
Заключение
Как видите, возможности верстки в Android весьма обширны: в данной статье весь функционал, кроме подсказок, реализован только версткой. Но это далеко не все.
В данной статье код XML намеренно оставлен неидеальным. Изучение базовых возможностей верстки и продвинутая оптимизация — это две разные темы. Конечно, настоящие гуру должны сразу писать оптимально. Но данная статья преследует учебные цели и рассчитана на начинающих разработчиков, поэтому я решил усложнять постепенно.
Всех желающих изучить пример оптимизации верстки в Android приглашаю прочесть и обсудить вторую часть данной статьи. В ней я рассматриваю следующие темы:
- использование строковых ресурсов
strings.xml
- собственные стили
styles.xml
и наследование стилей - темы
- ресурсы размерностей
dimens.xml
Эти вопросы будут изучены на примере оптимизации кода из первой части статьи. А пока благодарю всех, кто нашел время прочесть мою статью. Надеюсь, я смог показать что-то новое. Жду ваших отзывов и комментариев.
Полезные ссылки
- Готовый проект Android-приложения из данной статьи
- Тайны кнопок в Android. Часть 2: Рефакторинг верстки
- Верстка RelativeLayout
- Верстка Nine patch drawable
- Выравнивание текста в Button’ах и EditText’ах
- Поддержка экранов разных размеров и плотности
- Состояния, которые можно использовать в селекторе
- iPUMB — ПУМБ online — пример приложения, в котором я использовал описанные приемы верстки
Intermediate
Custom buttons in Android, we show you 13 techniques to style your buttons.
Miha Cirman
10 min read
We love custom buttons in Android apps; they are always part of your work. During all the years of mobile development, we had quite a few requests for button designs. We wanted to create a short list of examples for you so that you have a cheat sheet to work on your next project. Most of these design techniques work for many other types of components (e.g. ConstraintLayout, or any other View) as well.
We show you how to change colors, even how to make gradient colors. How to make a custom shape and how to add an image to a button and how to make a border for a button. Don’t worry CodeBrainer has 13 techniques for you to use.
You can make custom buttons in Android in many ways:
- Using colors (background, text, border)
- Using custom shapes like circle, rounded corners and more
- You can add images to your buttons to customize them
- Using drawables to make gradients, dotted borders and more
Normal button
Let’s start with a normal button. To add a button, that has an Android style all you need to do is to drag and drop a button from the Palette to your layout. For most versions that would mean a grey button with all corners at 2dp roundness. Check our blog, if you need to learn more about using Android Studio Layout Editor.
Change button colors
Having different colors of buttons makes your application shine. Most of the time designers choose different colors for a confirmation button (e.g. blue or green) and a cancel button (mostly red). We show you how to set a background, how to choose a custom color (and how to add it to resources) and how to make a gradient color.
Use tint to change color
We use tint to change the color of a button when we do not want to change the shape of the background. It means that we only change color, imagine that you have an icon in black and white and you want it to be blue. You use tint to make the icon blue.
First, you need to add a normal button. Then you need to change the backgrountTint attribute for that button. We used @android:color/holo_blue_dark for our color. However, you can select a color from Android resources.
Change the color of the text
To change the color of text, use attribute named textColor. As you can see on our example, we have a white color for text on our blueish button. To achieve the same effect, you need to set @android:color/white for textColor attribute.
Set color as a background
If you set value for background attribute with color type value, you make the shape of your button rectangular and a little bigger as well, because a normal button has a little bit of padding by default (see the button on the right) and setting color type value will override this setting. Sometimes you do not have to have the round corners, and this is just a perfect and simple way of changing the color. For the button above we have used the value @android:color/holo_blue_dark for the background and @android:color/white for the textColor.
Using custom color for a button
Sometimes you want to use a custom color. For this example, we use color #123abc. The simple way is to enter a value for attribute background. Since the color is dark we also set value @android:color/white to attribute textColor.
There is a better way to set a color, and this is to add a new resource value for a color.
First, you open the Resources window.
Then you switch to color resource.
After that, you can go ahead and add a new color value.
In the end, you enter the name and value for our color #123abc (we choose the name OurBlue)
Now you have a resource for the color, and you can use it all over your project by using value @color/OurBlue (or R.color.OurBlue in code). Values are in colors.xml
The values look something like this:
XML
Thanks for reading!
If you like our code, you can give back by sharing this article!
Gradient background for a button
Making gradient colors is fun. Because they look just like magic when one color changes to another, add a normal button to the layout. To play with the gradient, we need a new drawable resource file. So add one, we have named mine gradient_normal.xml.
Now that we have a drawable file we need to change its content. Write the code below into your new drawable.
XML
Thanks for reading!
If you like our code, you can give back by sharing this article!
You can see that the gradient has three color values, startColor, centerColor, endColor. If you want to make, more exciting examples change those three colors and replace them with your values. We also made our corners round using corners tag and 2dp value for the radius attribute.
For a button to have our gradient we need to set our drawable for a background attribute, so the value should be @drawable/gradient_normal (You can enter a value or use Resources window and select it)
Here you can read much more on drawable resources.
Shapes custom buttons in Android can have
Designers always give you instructions to make custom shapes for components like button in applications all the time. We show you a few ways to shape your buttons. First, we show you the most common, round corners as designers often choose different roundness size of corners for buttons. After that, we will make a circle button just for fun.
Buttons with rounded corners
As in the example for the gradient background, you have to add a new drawable for rounded corners as well, name it rounded_corners.xml. Inside the XML write the code:
XML
Thanks for reading!
If you like our code, you can give back by sharing this article!
First, we need a selector and an item inside. The primary tag for us is shape. We choose a rectangle for our value. Solid tag is for the background with color value (choose color/darker_gray for the value of color). Corners tag is the one we wanted. Put 10dp as a value. Note that you can mix the values for each corner. This way you get a different shape.
XML
Thanks for reading!
If you like our code, you can give back by sharing this article!
Now you can use your drawable for the background attribute of your button.
Change the shape of a button — Circle button
To make a button in the shape of a circle, we need a new drawable first. Name it circle.xml.
XML
Thanks for reading!
If you like our code, you can give back by sharing this article!
We need a selector, item, and shape. For the shape we use oval. To make the button in the shape of a circle, you need to make a button that has the same size for the width and height. We set the size with size tag (but this size is overridden with size on layout). We also set the color with solid to OurBlue.
Now you can use your drawable for the background attribute of your button. Since we used OurBlue color, make textColor white as well.
Images in buttons
Lots of designs for custom buttons in Android use images for buttons. We show you how to add an image to a button at the start of the text and the end of the text.
To add an image on the left side (or more precise before the start of the text; start/end automatically turns images around for countries that write from right to left) you need to set a value to attribute drawableStart. Choose one from the android resources with the Resources window. We use the value @android:drawable/ic_delete
To add an image to the right side (after the end of the text) use attribute drawableEnd. We use the value @android:drawable/btn_star
Android has a few icons already included, but if you do not know where to get images, we have a suggestion for you. You can use Google image search and use type: clipart. You can also check if the icon you want is in material design icons set or search some of the royalty-free sites for icons.
Learn how you can start creating apps with Flutter.
Learn more
Change borders of button
To create borders for buttons, you need a drawable as well. Name it border.xml. Inside that XML put the code:
XML
Thanks for reading!
If you like our code, you can give back by sharing this article!
The structure is the same selector, item, shape. For the shape we choose a rectangle value, if you want, you can choose oval and see what happens. To make the border, you need the stroke tag. You can select a color and width of the border with the stroke tag.
To use it use the border drawable for the background attribute.
Dashed border for a button that changes on click
Add a new drawable and name it border_dashed.xml.
XML
Thanks for reading!
If you like our code, you can give back by sharing this article!
There is one change to our code, and this is that we have two items. With the two item tags, we choose how the button looks in the normal state and how the button looks in the pressed state. You can change the values to make more of an effect, but we chose to resize the dash gap and size. To make dashes, we use stroke and attribute dashGap (size of space between lines) and dashWidth (size of line).
The ultimate custom buttons in Android
It is time to use all the skills of making custom buttons in Android. We have the gradient color of the button, but that gradient rotates when we press it. This example combines all the knowledge we have gained, and it gives you new ways to play with your custom buttons. Try changing colors, try changing the rotation.
Add drawable gradient.xml and add the code:
XML
Thanks for reading!
If you like our code, you can give back by sharing this article!
Conclusions
These are the techniques that help you create many scenarios for custom buttons in Android, let us know if you want some more examples. Making custom buttons is just one of the skills you need to know as an android developer; check our skills checklist for Android developers.
Also, remember, have fun coding with CodeBrainer.