В этом году на конференции Google IO компания Google представила новую библиотеку Android Design Support Library, которая создана для того, чтобы помочь разработчикам внедрять материальный дизайн в их приложения. Билиотека содержит много компонентов, нужных для этого нового стиля, и работает со всеми уровнями API, начиная с седьмого. Если по какой-то причине вы пропустили её анонс, можете ознакомиться с постом Ian Lake, выложенным на Android Developers Blog.
Встречайте Android CoordinatorLayout
Из всех компонентов, включенных в Android Design Support Library, наиболее интересным выглядит новый «прокачанный FrameLayout», он же герой нашей статьи — CoordinatorLayout. По названию можно догадаться, что CoordinatorLayout позволяет координировать некие зависимости между включенными в него виджетами.
Всё, что нужно сделать — обернуть необходимые нам виджеты в CoordinatorLayout. Давайте посмотрим, как это будет выглядеть в коде. Наш демонстрационный код очень прост — Floating Action Button, по нажатию на которую на экране появляется Snackbar.
Сначала добавим Support Design Library в gradle:
compile 'com.android.support:design:22.2.0'
Теперь создадим разметку для нашей Activity:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.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:src="@drawable/ic_done" /> </android.support.design.widget.CoordinatorLayout>
И, заодно, саму MainActivity:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Hello Snackbar", Snackbar.LENGTH_LONG).show(); } }); } }
Посмотрим на демо:
Круто, правда?
Но что если мы захотим использовать другую реализацию FAB? FAB из Support Library не умеет разворачиваться по нажатию на неё в список доступных опций (прим. переводчика: так, как это показано в спецификациях дизайна от самой Google), поэтому давайте-ка попробуем другую реализацию FAB:
compile 'com.getbase:floatingactionbutton:1.9.1'
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.getbase.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:fab_icon="@drawable/ic_done" /> </android.support.design.widget.CoordinatorLayout>
В этом случае CoordinatorLayout не работает из коробки, и связано это с тем, что наша новая FAB не имеет подключенной к ней реализации класса CoordinatorLayout.Behavior (прим. переводчика: далее по тексту будет использоваться слово «поведение»). Что можно сделать? Можно подождать, пока кто-нибудь не добавит её…
… или написать свою собственную реализацию CoordinatorLayout.Behavior, специфичную для FAB в нашем проекте.
Виджеты учатся вести себя правильно
Чем по-настоящему хорош CoordinatorLayout, так это тем, что нам не нужно иметь доступа к исходникам того виджета, для которого нужно реализовать его поведение. Также можно изменить поведение по умолчанию для любого виджета.
Сначала отнаследуемся от класса CoordinatorLayout.Behavior:
public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior<FloatingActionButton>
Добавим конструктор с параметрами Context и AttributeSet для того, чтобы наша реализация могла получить необходимые ей аттрибуты из xml-файла:
public FloatingActionButtonBehavior(Context context, AttributeSet attrs) {}
Следующий шаг — переопределить метод layoutDependsOn() и возвращать true только тогда, когда мы хотим отреагировать на происходящие в разметке изменения. В нашем случае, мы хотим реагировать только на изменения виджета Snackbar:
@Override public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) { return dependency instanceof SnackbarLayout; }
Теперь перейдем к реализации поведения. Метод onDependentViewChanged вызывается всякий раз, когда с виджетом, который находится в CoordinatorLayout и изменения которого мы отслеживаем, что-то происходит (прим. переводчика: имеются в виду изменения, приводящие к тому, что нужно пересчитать положение на экране виджета, для которого мы реализуем поведение, то есть понятно, что изменение, скажем, цвета Snackbar нас никак не интересует). В этом методе мы можем узнать текущее состояние Snackbar, и, соответственно, подвинуть FAB вверх, когда Snackbar появляется на экране. Для этого нужно изменить значение translationY у FAB на величину, равную высоте Snackbar. В начале анимации Snackbar, свойство translationY SnackBar’a выставлено в величину, равную высоте самого Snackbar, а значит, чтобы получить правильное значение translationY для FAB, нам нужно вычесть высоту Snackbar из его же translationY. Согласно документации, нам нужно вернуть true тогда, когда объект меняет своё положение на экране.
@Override public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) { float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight()); child.setTranslationY(translationY); return true; }
Последнее, что остаётся сделать — указать, что CoordinatorLayout должен использовать FloatingActionButtonBehavior. Сделать это можно в разметке:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.getbase.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:layout_behavior="com.getbase.coordinatorlayoutdemo.FloatingActionButtonBehavior" app:fab_icon="@drawable/ic_done" /> </android.support.design.widget.CoordinatorLayout>
И вот результат:
Если вы хотите указать для своего виджета поведение по умолчанию, пометьте его аннотацией DefaultBehavior, указав в параметрах аннотации путь к нужной вам реализации класса Behavior.
Хотите взглянуть на полную реализацию? Вам на github.
Приятного вам кодинга!
ссылка на оригинал статьи http://habrahabr.ru/post/265119/
Добавить комментарий