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

в 8:49, , рубрики: android, tutorial, мобильные приложения, перевод, Разработка под android, разработка приложений

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

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

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

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js