[Перевод] Введение в новый CoordinatorLayout
В этом году на конференции 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:
И, заодно, саму 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'
В этом случае CoordinatorLayout не работает из коробки, и связано это с тем, что наша новая FAB не имеет подключенной к ней реализации класса CoordinatorLayout.Behavior (прим. переводчика: далее по тексту будет использоваться слово «поведение»). Что можно сделать? Можно подождать, пока кто-нибудь не добавит её…
… или написать свою собственную реализацию CoordinatorLayout.Behavior, специфичную для FAB в нашем проекте.
Виджеты учатся вести себя правильно
Чем по-настоящему хорош CoordinatorLayout, так это тем, что нам не нужно иметь доступа к исходникам того виджета, для которого нужно реализовать его поведение. Также можно изменить поведение по умолчанию для любого виджета.
Сначала отнаследуемся от класса CoordinatorLayout.Behavior:
public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior
Добавим конструктор с параметрами 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. Сделать это можно в разметке:
И вот результат:
Если вы хотите указать для своего виджета поведение по умолчанию, пометьте его аннотацией DefaultBehavior, указав в параметрах аннотации путь к нужной вам реализации класса Behavior.
Хотите взглянуть на полную реализацию? Вам на github.
Приятного вам кодинга!