Как оформить и подключить иконки и кнопки в Android — кратко и практично
Короткий ответ: используйте VectorDrawable или адаптивные иконки для масштабируемости, MaterialButton (MD3) для кнопок, храните ресурсы в res/drawable и res/mipmap, и тестируйте на разных DPI и темах.
Основы иконок: форматы, размеры и где хранить
- Предпочтение — векторным иконкам (VectorDrawable). Они масштабируются без артефактов и уменьшают размер APK при правильной оптимизации.
- Когда нужен PNG: для сложной растровой графики или при поддержке старых API. Подготовьте версии для mdpi/hdpi/xhdpi/xxhdpi/xxxhdpi.
- Адаптивные иконки (launcher) — два слоя: foreground и background в res/mipmap-anydpi-v26/. Это обязательно для Android 8+.
- Пример VectorDrawable (res/drawable/ic_home.xml):
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportHeight="24">
<path android:fillColor="#000000"
android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"/>
</vector>
- Размещение: векторные и селекторы — res/drawable/, лаунчер-иконки — res/mipmap/. Имена ресурсов короткие и понятные: ic_home.xml, ic_search.xml.
При создании векторных иконок избегайте сложных фильтров и масок — они увеличивают время рендера и могут не поддерживаться на старых версиях.
Оформление кнопок и подключение drawable-ресурсов
- Используйте компоненты Material (MD3) — MaterialButton обеспечивает стили, иконки и состояние по умолчанию.
- XML-пример кнопки с иконкой:
<com.google.android.material.button.MaterialButton
android:id="@+id/myButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Домой"
android:icon="@drawable/ic_home"
app:iconGravity="start"
app:cornerRadius="12dp"
style="@style/Widget.Material3.Button.Primary"/>
- В Kotlin:
val btn = findViewById<MaterialButton>(R.id.myButton)
btn.setOnClickListener { /* действие */ }
btn.icon = ContextCompat.getDrawable(this, R.drawable.ic_home)
- Селектор для фоновых состояний (res/drawable/button_selector.xml):
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#E0E0E0"/>
<corners android:radius="8dp"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#FFFFFF"/>
<stroke android:width="1dp" android:color="#CCCCCC"/>
<corners android:radius="8dp"/>
</shape>
</item>
</selector>
- Темы: определяйте colorPrimary, colorOnPrimary в res/values/colors.xml и отдельные значения для res/values-night/colors.xml. Для состояний используйте color state lists.
Не задавайте фиксированные размеры иконкам в dp везде — используйте app:iconSize или задавайте в стиле, чтобы иконки адаптировались под разные плотности и размеры кнопок.
Адаптация UI, Compose и тестирование на разных экранах
- Макеты: ConstraintLayout для адаптивности; используйте layout_constraintDimensionRatio и chain для гибкого расположения.
- Размер иконок в кнопках: app:iconSize="24dp" для консистентности — но делайте размеры в ресурсах (dimens.xml) для масштабирования.
- Jetpack Compose — пример:
Button(onClick = { /* */ }, colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary)) {
Icon(Icons.Default.Home, contentDescription = "Домой")
Spacer(Modifier.size(ButtonDefaults.IconSpacing))
Text("Домой")
}
- Доступность: всегда указывайте contentDescription (или null для декоративных иконок), увеличивайте touch target до минимум 48dp.
- Производительность: отдавайте предпочтение VectorDrawable, используйте AnimatedVectorDrawable для простых анимаций; для сложной анимации — Lottie.
- Тестируйте: Layout Validation и Layout Inspector в Android Studio, эмуляторы с разными DPI и реальные устройства (360×640…1440×3200).
Частые ошибки
- Использование растровых PNG без множества density-версий → размытые иконки.
- Фиксированные размеры для кнопок и иконок, которые ломают адаптивность.
- Отсутствие contentDescription → плохая доступность.
- Использование сложных векторных эффектов, которые тормозят рендер.
FAQ
- Нужно ли всегда использовать VectorDrawable? Да, если иконка простая (контуры, заливки). Для фотографий — PNG/WebP.
- Где хранить иконки для лаунчера? В res/mipmap-anydpi-v26/ как адаптивные и в res/mipmap-*/ для PNG-версий.
- Как добавить разные состояния кнопки? Через selector в drawable или color state list для текстов/иконок.
Соблюдая эти шаги, вы получите компактный, масштабируемый и доступный UI: начните с Vector Asset, задайте темы MD3 и протестируйте на нескольких устройствах.