- PVSM.RU - https://www.pvsm.ru -
Данная статья является переводом статьи [1] Emrullah Luleci, а также её продолжения [2].
Нижний экран (Здесь и далее под «нижним экраном/слоем» будет подразумеваться элемент bottom sheet — прим. пер.) — компонент, выезжающий снизу экрана, который используется для отображения дополнительного контента. Подробнее об этом элементе можно узнать на официальной сайте посвященном материальному дизайну [3].

Для использования этого элемента, добавьте последние версии библиотек поддержки в свой проект:
dependencies {
//замените X.X.X номером последней версии
compile 'com.android.support:appcompat-v7:X.X.X'
compile 'com.android.support:design:X.X.X'
}
Создайте класс наследник от AppCompatActivity:
public class ButtonActivity extends AppCompatActivity {
...
}
Для удобства воспользуемся макетами. Назовем файл с нижним слоем bottom_sheet.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="340dp"
android:background="@android:color/darker_gray"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="80dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<TextView
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="@string/bottom_sheet_peek"
android:textColor="@android:color/white" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/bottom_sheet_content"
android:textColor="@android:color/white" />
</LinearLayout>
behavior_peekHeight: Определяет высоту видимой части.
behavior_hideable: Определяет, может ли нижний экран скрываться свайпом вниз.
Создайте CoordinatorLayout в качестве корневого вью. Добавьте в него прямым наследником bottom_sheet.xml. Элементы app_bar и activity_bottom_sheet_content не имеют прямого отношения к нижнему экрану, поэтому их можно заменить или удалить.
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.androidsample.BottomSheetActivity">
<!-- подключение элемента app bar -->
<include layout="@layout/app_bar" />
<!-- подключение основного контента -->
<include layout="@layout/activity_bottom_sheet_content" />
<!-- подключение нижнего экрана -->
<include layout="@layout/bottom_sheet" />
</android.support.design.widget.CoordinatorLayout>
На данном этапе нижний экран должен работать примерно так:

Поведением и свойствами нижнего экрана можно также управлять динамически с помощью Java.
// получение вью нижнего экрана
LinearLayout llBottomSheet = (LinearLayout) findViewById(R.id.bottom_sheet);
// настройка поведения нижнего экрана
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(llBottomSheet);
// настройка состояний нижнего экрана
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
// настройка максимальной высоты
bottomSheetBehavior.setPeekHeight(340);
// настройка возможности скрыть элемент при свайпе вниз
bottomSheetBehavior.setHideable(false);
// настройка колбэков при изменениях
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
Также можно прикрепить вью к нижнему экрану, чтобы прикрепленный элемент перемещался одновременно с нижним слоем.

Добавим Floating Action Button в макет созданный выше. Новый компонент должен являться непосредственным наследником CoordinatorLayout также как и bottom_sheet. Для прикрепления элемента к нижнему экрану необходимо добавить app:layout_anchor с id вью нижнего экрана, а также app:layout_anchorGravity со значением top|end.
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.androidsample.BottomSheetActivity">
<!-- подключение элемента app bar -->
<include layout="@layout/app_bar" />
<!-- подключение основного контента -->
<include layout="@layout/activity_bottom_sheet_content" />
<!-- подключение нижнего экрана -->
<include layout="@layout/bottom_sheet" />
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_vertical_margin"
android:src="@drawable/ic_add_shopping_cart_white_24dp"
android:theme="@style/PrimaryActionButton"
app:layout_anchor="@+id/bottom_sheet"
app:layout_anchorGravity="top|end" />
</android.support.design.widget.CoordinatorLayout>
Теперь плавающая кнопка закреплена в верхнем углу нашего нижнего экрана и перемещается вместе с ним.
Для скрытия кнопки при скроле необходимо добавить слушатель к нижнему экрану и отображать/скрывать кнопку. Для начала найдем необходимые вью:
fab = findViewById(R.id.fab);
View llBottomSheet = findViewById(R.id.bottom_sheet);
// настройка поведения нижнего экрана
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(llBottomSheet);
Если хотите, чтоб кнопка масштабировалась во время скрола, используйте это:
// настройка колбэков при изменениях
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
fab.animate().scaleX(1 - slideOffset).scaleY(1 - slideOffset).setDuration(0).start();
}
});
Для скрытия кнопки в момент начала скрола и отображения после полного сворачивания нижнего экрана, используйте следующее:
// настройка колбэков при изменениях
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
// этот код скрывает кнопку сразу же
// и отображает после того как нижний экран полностью свернется
if (BottomSheetBehavior.STATE_DRAGGING == newState) {
fab.animate().scaleX(0).scaleY(0).setDuration(300).start();
} else if (BottomSheetBehavior.STATE_COLLAPSED == newState) {
fab.animate().scaleX(1).scaleY(1).setDuration(300).start();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
Результат обоих вариантов можно увидеть ниже:

Вот и всё!
Автор: ArtiomCX75
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/tutorial/183587
Ссылки в тексте:
[1] статьи: https://medium.com/@emrullahluleci/android-bottom-sheet-30284293f066#.k38paaflf
[2] продолжения: https://medium.com/@emrullahluleci/android-anchoring-views-to-bottom-sheet-9c9069caf7d4#.n5m76rtlk
[3] материальному дизайну: https://material.google.com/components/bottom-sheets.html
[4] Источник: https://habrahabr.ru/post/309200/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.