5 проверенных способов изменить цвет Floating Action Button в Android
Для кого эта статья:
- Android-разработчики, стремящиеся улучшить интерфейс своих приложений
- Ученики и студенты курсов по программированию, заинтересованные в разработке мобильных приложений
Дизайнеры интерфейсов, желающие узнать больше о кастомизации элементов Material Design
Floating Action Button — фирменный элемент Material Design, который давно стал визитной карточкой Android-приложений. Яркая круглая кнопка с тенью, парящая над интерфейсом, привлекает внимание и указывает на главное действие. Но стандартный цвет FAB не всегда вписывается в вашу цветовую схему или брендинг. Недавно я разрабатывал финансовое приложение, где фиолетовый FAB выглядел чужеродно на фоне корпоративных синих оттенков. Пришлось освоить все методы кастомизации этого элемента. Поделюсь пятью рабочими способами изменить цвет FAB, чтобы сделать его гармоничной частью вашего UI. 🎨
Хотите стать Android-разработчиком с нуля? Курс Java-разработки от Skypro — ваш путь к созданию профессиональных мобильных приложений. От основ Java до продвинутых UI-компонентов вроде Floating Action Button. Студенты курса создают реальные проекты под руководством практикующих разработчиков. Бонус: модуль по Material Design и созданию адаптивного интерфейса для Android-приложений.
Что такое FAB и зачем менять его цвет в Android UI
Floating Action Button (FAB) — это круглая кнопка с иконкой, которая "парит" над интерфейсом приложения и представляет основное действие на экране. Компонент является частью библиотеки Material Design от Google и призван обеспечивать интуитивно понятный доступ к главной функции экрана.
Стандартный FAB имеет фиксированные параметры стиля, включая цвет фона, который по умолчанию наследуется от colorAccent или colorSecondary в теме приложения. Однако существует множество сценариев, когда требуется изменить его цветовую схему:
- Соответствие брендингу компании и фирменному стилю
- Улучшение контраста для повышения доступности приложения
- Создание визуальной иерархии, где разные цвета FAB указывают на разные типы действий
- Реализация динамических изменений цвета для обозначения различных состояний
- Обеспечение визуальной гармонии с остальными элементами интерфейса
Дмитрий Карпов, Senior Android Developer
Работая над банковским приложением, мы столкнулись с нетривиальной задачей — FAB должен был менять цвет в зависимости от баланса счёта. Зелёный для положительного баланса, жёлтый для околонулевого и красный для отрицательного. Изначально я использовал самый простой подход с XML, но быстро понял его ограниченность.
Пришлось перейти к программному изменению цвета, что позволило динамически реагировать на данные. Клиенты начали замечать этот небольшой визуальный индикатор: "О, кнопка покраснела — пора пополнять счёт!" Этот простой UX-приём значительно увеличил своевременность пополнений счетов и снизил количество уходов в овердрафт на 17%.
Прежде чем погрузиться в способы изменения цвета, важно понимать структуру FAB. Он состоит из нескольких элементов:
| Элемент FAB | Описание | Свойство для изменения цвета |
|---|---|---|
| Фон | Основной круглый элемент кнопки | backgroundTint |
| Иконка | Графическое изображение в центре | tint (для векторных drawable) |
| Рипл-эффект | Анимация при нажатии | rippleColor |
| Тень | Тень под кнопкой для эффекта "парения" | elevation, pressedTranslationZ |
Теперь рассмотрим пять проверенных способов изменения цвета FAB, начиная от самых простых до продвинутых техник. 🚀

Способ 1: Изменение цвета через XML атрибуты
Самый базовый и часто используемый подход к изменению цвета FAB — использование XML-атрибутов. Этот способ идеально подходит, когда цвет кнопки должен быть статическим и определен заранее.
Для начала убедитесь, что в вашем проекте подключена библиотека Material Components:
implementation 'com.google.android.material:material:1.9.0'
Теперь можно создать FAB в макете с нужным цветом:
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
android:contentDescription="@string/add_item"
app:backgroundTint="@color/custom_blue"
app:srcCompat="@drawable/ic_add" />
Ключевой атрибут здесь — app:backgroundTint, который управляет цветом фона кнопки. Вы можете указать конкретный цвет или ссылку на ресурс цвета из вашего файла colors.xml:
<!-- colors.xml -->
<resources>
<color name="custom_blue">#3F51B5</color>
<color name="custom_green">#4CAF50</color>
<color name="custom_orange">#FF9800</color>
</resources>
Для более тонкой настройки можно использовать селектор состояний, который позволяет определять разные цвета для разных состояний кнопки:
<!-- fab_color_selector.xml в каталоге res/color -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/custom_blue_dark" android:state_pressed="true" />
<item android:color="@color/custom_blue" />
</selector>
Затем используйте селектор как значение backgroundTint:
app:backgroundTint="@color/fab_color_selector"
Если вам нужно изменить цвет иконки FAB, используйте атрибут app:tint для векторных иконок:
app:tint="@color/white"
Или установите цвет непосредственно в векторном drawable:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:tint="@color/white"
... >
Преимущества и недостатки использования XML-атрибутов:
- ✅ Простота реализации — минимальный код
- ✅ Наглядность — все стили видны в XML макете
- ✅ Производительность — статические стили обрабатываются быстрее
- ❌ Отсутствие динамичности — сложно менять цвета в рантайме
- ❌ Ограниченность — некоторые эффекты требуют программного подхода
Способ 2: Программное изменение цвета FAB через код
Когда требуется динамически менять цвет FAB в ответ на действия пользователя или изменения данных, программное управление цветом становится незаменимым. Рассмотрим, как изменять цвет FAB через код на Java и Kotlin.
Алексей Смирнов, Lead Android Developer
В моём приложении для фитнеса пользователи жаловались на отсутствие понятной индикации режимов тренировки. У нас было три режима: кардио, силовая и растяжка. Переключались между ними через FAB, но не было понятно, какой режим активен.
Решил динамически менять цвет FAB: красный для кардио, синий для силовой и зелёный для растяжки. Используя программное изменение цвета, реализовал не только смену основного цвета, но и плавный переход между оттенками.
Результат превзошёл ожидания — количество ошибочных выборов режима упало на 78%, а средний рейтинг приложения вырос с 4.2 до 4.7. Пользователи особенно хвалили "интуитивность интерфейса" и "понятную цветовую индикацию". Никто не догадывался, что решение было реализовано буквально за час.
Java-реализация:
FloatingActionButton fab = findViewById(R.id.fab);
// Изменение цвета фона
fab.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#FF4081")));
// Изменение цвета иконки
fab.setImageTintList(ColorStateList.valueOf(Color.WHITE));
// Изменение цвета эффекта пульсации (ripple)
fab.setRippleColor(ColorStateList.valueOf(Color.parseColor("#B3FF4081")));
Kotlin-реализация:
val fab: FloatingActionButton = findViewById(R.id.fab)
// Изменение цвета фона
fab.backgroundTintList = ColorStateList.valueOf(Color.parseColor("#FF4081"))
// Изменение цвета иконки
fab.imageTintList = ColorStateList.valueOf(Color.WHITE)
// Изменение цвета эффекта пульсации (ripple)
fab.rippleColor = ColorStateList.valueOf(Color.parseColor("#B3FF4081"))
Для работы с цветами из ресурсов используйте:
// Java
fab.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(this, R.color.custom_blue)));
// Kotlin
fab.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(this, R.color.custom_blue))
Обратите внимание на различия между методами установки цвета:
| Метод | Применение | API Level | Особенности |
|---|---|---|---|
| setBackgroundTintList() | Изменение цвета фона FAB | 21+ | Основной метод для Material Components |
| setBackgroundColor() | Не рекомендуется для FAB | Все | Может сломать эффект тени и форму FAB |
| setColorFilter() | Устаревший метод для иконок | Все (устаревший) | Заменён на setImageTintList |
| setImageTintList() | Изменение цвета иконки | 21+ | Работает только с векторными drawable |
Для более сложных случаев можно создавать программно селекторы состояний:
// Java
int[][] states = new int[][] {
new int[] { android.R.attr.state_pressed }, // Pressed state
new int[] { } // Default state
};
int[] colors = new int[] {
ContextCompat.getColor(this, R.color.custom_blue_dark), // Pressed color
ContextCompat.getColor(this, R.color.custom_blue) // Default color
};
ColorStateList colorStateList = new ColorStateList(states, colors);
fab.setBackgroundTintList(colorStateList);
// Kotlin
val states = arrayOf(
intArrayOf(android.R.attr.state_pressed), // Pressed state
intArrayOf() // Default state
)
val colors = intArrayOf(
ContextCompat.getColor(this, R.color.custom_blue_dark), // Pressed color
ContextCompat.getColor(this, R.color.custom_blue) // Default color
)
val colorStateList = ColorStateList(states, colors)
fab.backgroundTintList = colorStateList
Преимущества программного изменения цвета:
- ✅ Гибкость — можно менять цвета в ответ на любые события
- ✅ Динамичность — поддержка изменения цветов во время выполнения
- ✅ Больше контроля — возможность создавать сложные селекторы программно
- ❌ Больше кода по сравнению с XML-подходом
- ❌ Сложнее отлаживать визуальные эффекты
Способ 3: Создание анимации и переходов цвета FAB
Плавные цветовые переходы могут существенно улучшить UX вашего приложения, делая интерфейс более живым и отзывчивым. В Android есть несколько способов анимировать изменение цвета FAB. 🎭
Начнем с простого примера использования ValueAnimator для плавного перехода между двумя цветами:
// Java
private void animateFabColor(FloatingActionButton fab, int colorFrom, int colorTo) {
ValueAnimator colorAnimation = ValueAnimator.ofObject(
new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.setDuration(300); // 300ms для плавного перехода
colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
fab.setBackgroundTintList(
ColorStateList.valueOf((int) animator.getAnimatedValue()));
}
});
colorAnimation.start();
}
// Пример использования
animateFabColor(fab,
ContextCompat.getColor(this, R.color.custom_blue),
ContextCompat.getColor(this, R.color.custom_green));
// Kotlin
private fun animateFabColor(fab: FloatingActionButton, colorFrom: Int, colorTo: Int) {
val colorAnimation = ValueAnimator.ofObject(
ArgbEvaluator(), colorFrom, colorTo)
colorAnimation.duration = 300 // 300ms для плавного перехода
colorAnimation.addUpdateListener { animator ->
fab.backgroundTintList = ColorStateList.valueOf(
animator.animatedValue as Int)
}
colorAnimation.start()
}
Для более сложных анимаций можно использовать ObjectAnimator или AnimatorSet:
// Java
private void pulseFabColor(FloatingActionButton fab, int colorNormal, int colorHighlight) {
ObjectAnimator colorFade = ObjectAnimator.ofObject(
fab,
"backgroundTintList",
new ArgbEvaluatorHolder(),
ColorStateList.valueOf(colorNormal),
ColorStateList.valueOf(colorHighlight));
colorFade.setDuration(500);
colorFade.setRepeatCount(1);
colorFade.setRepeatMode(ValueAnimator.REVERSE);
colorFade.start();
}
// Класс-адаптер для работы с ColorStateList в ObjectAnimator
public class ArgbEvaluatorHolder implements TypeEvaluator<ColorStateList> {
private final ArgbEvaluator evaluator = new ArgbEvaluator();
@Override
public ColorStateList evaluate(float fraction, ColorStateList startValue,
ColorStateList endValue) {
int color = (int) evaluator.evaluate(fraction,
startValue.getDefaultColor(),
endValue.getDefaultColor());
return ColorStateList.valueOf(color);
}
}
// Kotlin
private fun pulseFabColor(fab: FloatingActionButton, colorNormal: Int, colorHighlight: Int) {
val colorFade = ObjectAnimator.ofObject(
fab,
"backgroundTintList",
ArgbEvaluatorHolder(),
ColorStateList.valueOf(colorNormal),
ColorStateList.valueOf(colorHighlight))
colorFade.duration = 500
colorFade.repeatCount = 1
colorFade.repeatMode = ValueAnimator.REVERSE
colorFade.start()
}
// Класс-адаптер для работы с ColorStateList в ObjectAnimator
class ArgbEvaluatorHolder : TypeEvaluator<ColorStateList> {
private val evaluator = ArgbEvaluator()
override fun evaluate(fraction: Float, startValue: ColorStateList,
endValue: ColorStateList): ColorStateList {
val color = evaluator.evaluate(
fraction,
startValue.defaultColor,
endValue.defaultColor) as Int
return ColorStateList.valueOf(color)
}
}
Еще один мощный способ анимации — использование Motion Layout, который позволяет создавать сложные анимации с минимальным кодом:
<!-- motion_scene.xml -->
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end"
motion:duration="500">
<OnClick
motion:targetId="@id/fab"
motion:clickAction="toggle" />
<KeyFrameSet>
<KeyAttribute
motion:framePosition="0"
motion:target="@id/fab"
motion:transitionEasing="decelerate"
android:backgroundTint="@color/custom_blue" />
<KeyAttribute
motion:framePosition="100"
motion:target="@id/fab"
motion:transitionEasing="accelerate"
android:backgroundTint="@color/custom_green" />
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="@+id/start">
<!-- Начальные ограничения -->
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<!-- Конечные ограничения -->
</ConstraintSet>
</MotionScene>
Для создания непрерывного "дышащего" эффекта с изменением цвета можно использовать бесконечную анимацию:
// Java
private void startBreathingAnimation(FloatingActionButton fab) {
ObjectAnimator colorAnimator = ObjectAnimator.ofArgb(
fab,
"backgroundTint",
Color.RED,
Color.BLUE);
colorAnimator.setDuration(2000);
colorAnimator.setRepeatCount(ObjectAnimator.INFINITE);
colorAnimator.setRepeatMode(ValueAnimator.REVERSE);
colorAnimator.setEvaluator(new ArgbEvaluator());
colorAnimator.start();
}
// Kotlin
private fun startBreathingAnimation(fab: FloatingActionButton) {
val colorAnimator = ObjectAnimator.ofArgb(
fab,
"backgroundTint",
Color.RED,
Color.BLUE)
colorAnimator.duration = 2000
colorAnimator.repeatCount = ObjectAnimator.INFINITE
colorAnimator.repeatMode = ValueAnimator.REVERSE
colorAnimator.setEvaluator(ArgbEvaluator())
colorAnimator.start()
}
Варианты применения анимации цвета FAB:
- Индикация прогресса длительной операции
- Привлечение внимания к новым функциям
- Визуализация смены состояния (например, запись → пауза)
- Подтверждение успешного действия (мигание зеленым)
- Предупреждение об ошибке (пульсация красным)
Способ 4: Стилизация FAB для разных состояний активности
В Material Design FAB может находиться в различных состояниях: нормальное, нажатое, отключенное и т.д. Для каждого из этих состояний можно задать свой цвет, создавая более отзывчивый и информативный интерфейс. 🎨
Рассмотрим, как реализовать разные цвета FAB для разных состояний активности.
Вариант 1: Использование селектора состояний в XML
Создадим файл селектора цветов в папке res/color:
<!-- res/color/fab_color_state_list.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/fab_disabled" android:state_enabled="false" />
<item android:color="@color/fab_pressed" android:state_pressed="true" />
<item android:color="@color/fab_focused" android:state_focused="true" android:state_enabled="true" />
<item android:color="@color/fab_normal" /> <!-- Default state -->
</selector>
Теперь используем этот селектор в нашем FAB:
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
app:backgroundTint="@color/fab_color_state_list"
app:srcCompat="@drawable/ic_add" />
Аналогично можно создать селектор для цвета иконки:
<!-- res/color/fab_icon_color_state_list.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/icon_disabled" android:state_enabled="false" />
<item android:color="@color/icon_normal" />
</selector>
И применить его:
app:tint="@color/fab_icon_color_state_list"
Вариант 2: Программное создание селектора состояний
// Java
private void setFabStateColors(FloatingActionButton fab) {
int[][] states = new int[][] {
new int[] { -android.R.attr.state_enabled }, // Disabled state
new int[] { android.R.attr.state_pressed }, // Pressed state
new int[] { android.R.attr.state_focused }, // Focused state
new int[] { } // Default state
};
int[] colors = new int[] {
Color.GRAY, // Disabled color
Color.parseColor("#A52A2A"), // Pressed color (Brown)
Color.parseColor("#FFA500"), // Focused color (Orange)
Color.parseColor("#1E90FF") // Default color (Dodger Blue)
};
ColorStateList colorStateList = new ColorStateList(states, colors);
fab.setBackgroundTintList(colorStateList);
}
// Kotlin
private fun setFabStateColors(fab: FloatingActionButton) {
val states = arrayOf(
intArrayOf(-android.R.attr.state_enabled), // Disabled state
intArrayOf(android.R.attr.state_pressed), // Pressed state
intArrayOf(android.R.attr.state_focused), // Focused state
intArrayOf() // Default state
)
val colors = intArrayOf(
Color.GRAY, // Disabled color
Color.parseColor("#A52A2A"), // Pressed color (Brown)
Color.parseColor("#FFA500"), // Focused color (Orange)
Color.parseColor("#1E90FF") // Default color (Dodger Blue)
)
val colorStateList = ColorStateList(states, colors)
fab.backgroundTintList = colorStateList
}
Для более полного контроля над внешним видом FAB в разных состояниях, можно определить стиль в themes.xml:
<!-- themes.xml -->
<style name="CustomFabStyle" parent="Widget.MaterialComponents.FloatingActionButton">
<item name="backgroundTint">@color/fab_color_state_list</item>
<item name="tint">@color/fab_icon_color_state_list</item>
<item name="rippleColor">@color/fab_ripple_color_state_list</item>
<item name="elevation">6dp</item>
<item name="pressedTranslationZ">12dp</item>
</style>
И применить его к FAB:
<com.google.android.material.floatingactionbutton.FloatingActionButton
style="@style/CustomFabStyle"
... />
Состояния FAB, которые можно стилизовать:
| Состояние | XML атрибут | Примечание |
|---|---|---|
| Нормальное | По умолчанию (без атрибутов) | Основное состояние кнопки |
| Нажатое | android:state_pressed="true" | Когда пользователь нажимает на кнопку |
| Отключенное | android:state_enabled="false" | Когда кнопка неактивна (fab.setEnabled(false)) |
| В фокусе | android:state_focused="true" | Когда кнопка получает фокус ввода |
| Выбранное | android:state_selected="true" | Для состояния выбора (fab.setSelected(true)) |
| Активированное | android:state_activated="true" | Особое состояние активации (fab.setActivated(true)) |
Для реагирования на изменения состояний можно также использовать слушатели:
// Java
fab.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Изменение цвета при нажатии
fab.setBackgroundTintList(
ColorStateList.valueOf(Color.parseColor("#A52A2A")));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// Возврат к исходному цвету
fab.setBackgroundTintList(
ColorStateList.valueOf(Color.parseColor("#1E90FF")));
break;
}
// Возвращаем false, чтобы стандартный обработчик onClick тоже сработал
return false;
}
});
// Kotlin
fab.setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
// Изменение цвета при нажатии
fab.backgroundTintList =
ColorStateList.valueOf(Color.parseColor("#A52A2A"))
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
// Возврат к исходному цвету
fab.backgroundTintList =
ColorStateList.valueOf(Color.parseColor("#1E90FF"))
}
}
// Возвращаем false, чтобы стандартный обработчик onClick тоже сработал
false
}
Такой подход к стилизации FAB для различных состояний позволяет создавать более интерактивные и отзывчивые интерфейсы, что значительно улучшает UX вашего приложения. 🚀
Изменение цвета Floating Action Button — это мощный инструмент для улучшения пользовательского опыта, который выходит далеко за рамки простой эстетики. Правильно подобранные цвета и анимации превращают FAB из простой кнопки в интуитивный коммуникационный канал между приложением и пользователем. Не ограничивайтесь базовыми настройками — экспериментируйте с состояниями, переходами и анимациями. В конечном счете, именно такие небольшие детали делают ваше приложение запоминающимся и выделяют его среди конкурентов.