- PVSM.RU - https://www.pvsm.ru -

Android: выдвигающийся экран снизу

Данная статья является переводом статьи [1] Emrullah Luleci, а также её продолжения [2].

Нижний экран (Здесь и далее под «нижним экраном/слоем» будет подразумеваться элемент bottom sheet — прим. пер.) — компонент, выезжающий снизу экрана, который используется для отображения дополнительного контента. Подробнее об этом элементе можно узнать на официальной сайте посвященном материальному дизайну [3].

image

Зависимости

Для использования этого элемента, добавьте последние версии библиотек поддержки в свой проект:

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.

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: Определяет, может ли нижний экран скрываться свайпом вниз.

Container view

Создайте 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>

На данном этапе нижний экран должен работать примерно так:

image

Динамическое управление

Поведением и свойствами нижнего экрана можно также управлять динамически с помощью 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) {

    }
});

Прикрепление элементов к нижнему экрану

Также можно прикрепить вью к нижнему экрану, чтобы прикрепленный элемент перемещался одновременно с нижним слоем.

image

Добавим 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) {
    }
});

Результат обоих вариантов можно увидеть ниже:

image

Вот и всё!

Автор: 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