Android Button Icon: способы добавить иконку на кнопку

Кнопка с иконкой в Android чаще всего реализуется одним из трёх способов: через ImageButton, через MaterialButton с атрибутом app:icon или через обычный Button с атрибутом android:drawableStart. Выбор зависит от того, нужен ли на кнопке текст, какая библиотека подключена к проекту и как выглядит дизайн-макет.

Ниже разберём каждый вариант с примерами XML и Kotlin, покажем, какие размеры иконок использовать, и разберём типичные ошибки — например, когда иконка не отображается, растягивается или игнорирует цвет из темы.

ImageButton: кнопка-иконка без текста

Если кнопка должна состоять только из иконки (корзина, «поделиться», воспроизведение), подходит ImageButton. Иконка задаётся через android:src, а фон — через android:background.

<ImageButton

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@drawable/ic_play"

android:background="?attr/selectableItemBackgroundBorderless"

android:contentDescription="@string/play" />

Атрибут android:contentDescription обязателен для доступности: без него TalkBack не сможет озвучить назначение кнопки, а Lint выдаст предупреждение. Фон ?attr/selectableItemBackgroundBorderless даёт круглый ripple-эффект при нажатии без видимой рамки.

MaterialButton с атрибутом app:icon

Самый гибкий современный вариант — MaterialButton из библиотеки Material Components. Иконка добавляется атрибутом app:icon, и её можно разместить слева, справа, сверху или снизу относительно текста через app:iconGravity.

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

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Скачать"

app:icon="@drawable/ic_download"

app:iconGravity="textStart"

app:iconTint="@color/white"

app:iconSize="20dp" />

Чтобы app:icon работал, в проекте должна быть подключена зависимость Material Components и тема приложения должна наследоваться от Theme.MaterialComponents (или её потомка). Иначе атрибут либо не применится, либо приложение упадёт при инфлейте разметки.

⚠️ Внимание: если app:icon игнорируется, первым делом проверьте родительскую тему приложения в themes.xml. Тема Theme.AppCompat не поддерживает атрибуты MaterialButton — это самая частая причина «пропадающей» иконки.
📊 Какой способ добавления иконки на кнопку вы используете чаще всего?
MaterialButton с app:icon
ImageButton
Button с drawableStart
Своя кастомная View

Обычный Button с drawableStart

Если Material Components в проекте нет и подключать её не хочется, иконку можно пристроить к стандартному Button через android:drawableStart (или устаревший android:drawableLeft).

<Button

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Отправить"

android:drawableStart="@drawable/ic_send"

android:drawablePadding="8dp" />

Отступ между иконкой и текстом регулируется android:drawablePadding. У этого способа есть ограничения: размер drawable нельзя задать напрямую в XML, тинт применяется сложнее, а позиционирование ограничено четырьмя сторонами. Программно drawable с нужными границами задаётся так:

val icon = ContextCompat.getDrawable(this, R.drawable.ic_send)

icon?.setBounds(0, 0, icon.intrinsicWidth, icon.intrinsicHeight)

button.setCompoundDrawables(icon, null, null, null)

Сравнение способов

Чтобы выбрать подходящий вариант, удобно свериться с таблицей возможностей каждого подхода.

СпособТекст + иконкаРазмер иконки в XMLТинт из темыЗависимости
ImageButtonНет, только иконкаДа (scaleType)Через app:tintНет
MaterialButton + app:iconДаДа (app:iconSize)Да (app:iconTint)Material Components
Button + drawableStartДаНетОграниченноНет
Кастомная ViewДа, любая компоновкаДаДаНет

Размеры и форматы иконок

По гайдлайнам Material Design стандартный размер иконки на кнопке — 18–24 dp, а минимальная область нажатия (touch target) — 48×48 dp. Если визуально иконка меньше, увеличьте область нажатия через android:minWidth/android:minHeight или padding.

Предпочтительный формат — векторный VectorDrawable. PNG придётся готовить в нескольких плотностях (mdpi–xxxhdpi), иначе на части экранов иконка будет размытой.

  • 🎨 Иконку создавайте через Vector Asset Studio — там есть встроенная библиотека Material Icons.
  • 📐 Держите размер иконки в пределах 18–24 dp относительно текста кнопки.
  • 🌈 Цвет задавайте через app:iconTint или атрибуты темы, а не «зашивайте» в саму иконку.

Программное управление иконкой

Иногда иконку нужно менять динамически — например, переключать «пауза/воспроизведение». Для MaterialButton это делается методом setIcon():

val button = findViewById<MaterialButton>(R.id.playButton)

button.setIconResource(R.drawable.ic_pause)

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

Для ImageButton используется setImageResource(). Обратите внимание: setIcon() у MaterialButton принимает Drawable, а setIconResource() — id ресурса; путать их не стоит.

☑️ Проверка кнопки с иконкой перед релизом

Выполнено: 0 / 5

Типичные проблемы и их решения

Иконка есть в ресурсах, но на кнопке не отображается. Возможные причины: тема не от Material Components, иконка задана через android:icon вместо app:icon (у MaterialButton нужен именно префикс app), либо drawable повреждён.

Иконка чёрная, хотя в макете белая. VectorDrawable по умолчанию использует цвет, зашитый в android:fillColor. Переопределите его через app:iconTint или app:tint, указав цвет из темы — например, ?attr/colorOnPrimary.

⚠️ Внимание: не используйте android:tint и app:tint одновременно на одной View — поведение на разных версиях Android может отличаться. Для MaterialButton применяйте только app:iconTint.

Иконка растянулась на весь размер кнопки. Такое случается с ImageButton, когда заданы match_parent и не настроен android:scaleType. Установите scaleType="centerInside" или fitCenter, чтобы сохранить пропорции.

Почему drawableStart не тинтуется автоматически

Compound drawables у обычного Button не наследуют цвет текста. Начиная с AppCompat можно использовать app:drawableTint, но поддержка зависит от версии библиотеки. Надёжнее либо перекрасить сам VectorDrawable, либо перейти на MaterialButton, где тинт иконки работает предсказуемо.

FAQ

Как добавить иконку справа от текста на MaterialButton?

Используйте атрибут app:iconGravity="textEnd" или end. Для обычного Button аналог — android:drawableEnd.

Можно ли использовать две иконки на одной кнопке?

Штатно MaterialButton поддерживает одну иконку. Для двух иконок придётся собрать кастомную разметку — например, LinearLayout с двумя ImageView и TextView, оформленный как кнопка.

Почему иконка не видна в превью Android Studio?

Проверьте, что drawable лежит в правильной папке ресурсов и что в превью выбрана тема, наследующаяся от Material Components. Иногда помогает пересборка проекта через Build → Rebuild Project.

Что лучше для иконок: PNG или VectorDrawable?

Векторный формат предпочтительнее: один файл на все плотности экрана, меньший размер APK и простое перекрашивание через тинт. PNG оправдан только для сложной растровой графики.

Как сделать круглую кнопку с иконкой по центру?

Используйте FloatingActionButton с app:srcCompat — это штатный компонент для круглой кнопки-иконки. Либо задайте MaterialButton атрибут app:cornerRadius, равный половине высоты, и app:iconGravity="textStart" без текста.