Ниже рассказываеться как создать кнопки в стиле Twitter Bootstrap для Android приложения. Данный стиль взят для примера что бы разобраться в концпеции создания собственных стилей. Пример кода выложен на github. Репозeторий будет попoлняться примерами для других элементов. Так что можно подписываться. Коллаборатация также приветствуеться.
Android SDK предлагает несколько вариантов для создания собственных стилей.
Начнём с самого простого. Создададим кнопку на основе нескольких графических файлов отображающих отдельные состояни кнопок. (default, selected, focused, pressed и т.д.) Поддерживаются форматы .png, .jpg, или .gif.
Добавляем в активити код для кнопки.
<Button
android:id="@+id/button_primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/default_margin"
android:background="@drawable/button_primary_selector"
android:text="Button"
android:textColor="@android:color/white" />
В папке res/drawable создаём файл button_primary_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/button_primary_selected"/>
<item android:state_pressed="true" android:drawable="@drawable/button_primary_pressed"/>
<item android:state_focused="true" android:drawable="@drawable/button_primary_focused"/>
<item android:drawable="@drawable/button_primary_normal"/>
</selector>
Этот файл делает роутинг графиков в зависимости от текущего состояния кнопки
Добавляем графики для каждого состояния кнопки в ту же папку. Расширение файла указывать не надо. Недостатком данного примера являеться невозможность динамического скалирования кнопок.
Использование формата Nine-Patch File
Решаем проблему скалирования элементов следующим образом. В случае кнопки нужны по крайней мере два png файла соответствующие нормальному и нажатому состояниям.
Исходный график нормального состояния для primary button
Конвертация происходит с помощью утилиты draw9patch. Её можно найти в ANDROID_SDK_HOME/tools/.
После запуска перетягиваем график в открывшееся окно. И по краю картинки помечаем пиксели входящие в скалируемого контента. Примерно так
Справа предлагается превью. Если результат удовлетворительный. Через меню сохраняем файл в папку drawable. Повторяем процедуру для графиков всех состояний кнопки.
Подключение кнопки происходит также как в предыдущем примере
Shape Drawable
Вместо графиков можно описывать элементы с помощью XML.
Пример селектора для двух состояний:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<gradient
android:startColor="#002A80"
android:endColor="#04C"
android:angle="270" />
<stroke
android:width="1dp"
android:color="#04C" />
<corners
android:radius="4dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
<item>
<shape>
<gradient
android:startColor="#006DCC"
android:endColor="#04C"
android:angle="270" />
<stroke
android:width="1dp"
android:color="#04C" />
<corners
android:radius="4dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
</selector>
При изменении состояния файл читаеться сверху вниз и первый элемент с подходящим статусом будет выполнен.
Последний элемент в данном примере будет выполняться если состояние предыдущих элементов не соответствует состоянию кнопки.
Этот пример можно дополнить для отображения других состояний добавив элементы item с соответствующим атрибутом
Например для selected
...
android:state_selected="true"
...
Описание состояний можно также вынести в отдельные файлы. Например для нажатая кнопка будет описываться так в файле button_primary_pressed.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:startColor="#04C"
android:endColor="#006DCC"
android:angle="270" />
<stroke
android:width="1dp"
android:color="#04C" />
<corners
android:radius="4dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
</selector>
В селекторе расширение (.xml) также не указывается.
Вместо StateList можно также использовать LayerList. Этот подход отличаеться от предудыщего тем что элементы не имеют атрибута состояния. Все элементы будут отработаны. Последний элемент отрисовываеться сверху.
Пример:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap android:src="@drawable/android_red"
android:gravity="center" />
</item>
<item android:top="10dp" android:left="10dp">
<bitmap android:src="@drawable/android_green"
android:gravity="center" />
</item>
<item android:top="20dp" android:left="20dp">
<bitmap android:src="@drawable/android_blue"
android:gravity="center" />
</item>
</layer-list>
В результате получаем
Примеры кода для создания стиля кнопок с помощью StateList и Shape Drawable можно посмотреть здесьandroid-custom-style-ui.
Автор: xreader