Одно из самых значительных изменений в дизайне Android было представлено во время конференции Google I / O 2014 года — дизайн материалов . Несмотря на то, что Google представила набор рекомендаций для своей новой философии дизайна, разработчики отвечали за внедрение новых шаблонов с нуля.
Это привело ко многим сторонним библиотекам, которые достигли целей дизайна материалов с похожими, но разными реализациями. Чтобы облегчить некоторые трудности разработки материалов, Google представил библиотеку поддержки проектирования во время основного выступления на конференции Google I / O 2015 года .
Как и во многих других аспектах разработки программного обеспечения, библиотека поддержки проектирования со временем улучшилась, добавив поддержку нижних листов в выпуске 23.2. В этой статье вы узнаете, как легко внедрить шаблон нижнего листа в ваши собственные приложения. Пример проекта для этой статьи можно найти на GitHub .
1. Настройка нижнего листа
Для реализации нижнего листа у вас есть два варианта: представление контейнера с BottomSheetBehavior
в файле макета или BottomSheetDialogFragment
. Чтобы использовать любой из них, вам необходимо импортировать в ваш проект библиотеку поддержки проектирования с минимальной версией 23.2 . Вы можете сделать это в build.gradle , включив следующую строку в dependencies
:
1
|
compile ‘com.android.support:design:23.2.0’
|
После синхронизации проекта с библиотекой поддержки проектирования вы можете открыть файл макета, который должен содержать нижний лист. В нашем примере проекта я использую следующий XML, который отображает три кнопки в activity_main.xml .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
<android.support.design.widget.CoordinatorLayout
xmlns:android=»http://schemas.android.com/apk/res/android»
xmlns:app=»http://schemas.android.com/apk/res-auto»
android:id=»@+id/main_content»
android:layout_width=»match_parent»
android:layout_height=»match_parent»
android:fitsSystemWindows=»true»>
<ScrollView
android:layout_width=»match_parent»
android:layout_height=»match_parent»
app:layout_behavior=»@string/appbar_scrolling_view_behavior»>
<LinearLayout
android:layout_width=»match_parent»
android:layout_height=»match_parent»
android:orientation=»vertical»
android:paddingTop=»24dp»>
<Button
android:id=»@+id/button_1″
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:text=»Button 1″
android:padding=»16dp»
android:layout_margin=»8dp»
android:textColor=»@android:color/white»
android:background=»@android:color/holo_green_dark»/>
<Button
android:id=»@+id/button_2″
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:padding=»16dp»
android:layout_margin=»8dp»
android:text=»Button 2″
android:textColor=»@android:color/white»
android:background=»@android:color/holo_blue_light»/>
<Button
android:id=»@+id/button_3″
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:padding=»16dp»
android:layout_margin=»8dp»
android:text=»Button 3″
android:textColor=»@android:color/white»
android:background=»@android:color/holo_red_dark»/>
</LinearLayout>
</ScrollView>
<android.support.v4.widget.NestedScrollView
android:id=»@+id/bottom_sheet»
android:layout_width=»match_parent»
android:layout_height=»350dp»
android:clipToPadding=»true»
android:background=»@android:color/holo_orange_light»
app:layout_behavior=»android.support.design.widget.BottomSheetBehavior»
>
<TextView
android:layout_width=»match_parent»
android:layout_height=»match_parent»
android:text=»@string/ipsum»
android:padding=»16dp»
android:textSize=»16sp»/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
|
При запуске на устройстве макет выглядит следующим образом:
В файле макета есть несколько ключевых моментов, о которых вам нужно знать. Чтобы использовать виджет нижних листов, вы должны использовать контейнер CoordinatorLayout
для представлений. Внизу файла вы заметили, что есть NestedScrollView
содержащий TextView
. Хотя любое представление контейнера можно использовать на нижнем листе, прокрутка может происходить надлежащим образом, только если вы используете контейнер, поддерживающий вложенную прокрутку, например NestedScrollView
или RecyclerView
.
Чтобы контейнер распознавался библиотекой поддержки проектирования как контейнер нижнего листа, необходимо включить атрибут layout_behavior
и присвоить ему значение android.support.design.widget.BottomSheetBehavior
. Вы можете видеть это, использованное выше в NestedScrollView
.
Другим ключевым атрибутом, который следует отметить для контейнера нижнего листа, является layout_height
. Какими бы ни были размеры вашего элемента контейнера, он контролирует отображение нижнего листа. Есть одна оговорка, о которой следует помнить с высотой нижнего листа. Если вы используете CoordinatorLayout
для перемещения других объектов View
, например, с помощью CollapsingToolbarLayout
, то высота вашего нижнего листа изменится. Это может вызвать нежелательный эффект прыжка.
2. Отображение макета на основе нижнего листа
После того, как вы добавили контейнер вида и правильно настроили его в файле макета, вы можете открыть действие или Fragment
который использует нижний лист. В примере проекта это MainActivity.java .
Чтобы ваш нижний лист отображался, вам нужно создать BottomSheetBehavior
. Это создается путем получения ссылки на представление контейнера и вызова BottomSheetBehavior.from()
для этого контейнера. В этом примере вы также ссылаетесь на три кнопки из макета и вызываете на них setOnClickListener()
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
private BottomSheetBehavior mBottomSheetBehavior;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View bottomSheet = findViewById( R.id.bottom_sheet );
Button button1 = (Button) findViewById( R.id.button_1 );
Button button2 = (Button) findViewById( R.id.button_2 );
Button button3 = (Button) findViewById( R.id.button_3 );
button1.setOnClickListener(this);
button2.setOnClickListener(this);
button3.setOnClickListener(this);
mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
}
|
Теперь, когда вы создали BottomSheetBehavior
, последнее, что вам нужно сделать, это показать свой нижний лист View
. Вы можете сделать это, установив состояние вашего BottomSheetBehavior
в STATE_EXPANDED
, что мы делаем в примере приложения при нажатии верхней Button
.
1
2
3
4
5
6
7
8
9
|
@Override
public void onClick(View v) {
switch( v.getId() ) {
case R.id.button_1: {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
break;
}
}
}
|
Когда это будет сделано, ваше приложение должно выглядеть так:
Чтобы скрыть нижний лист, пользователь может провести его вниз, чтобы скрыть от экрана, или вы можете установить BottomSheetBehavior
в STATE_COLLAPSED
.
3. Подглядывать нижний лист
Возможно, вы заметили, что в различных приложениях и виджетах для Android от Google, таких как Place Picker из Places API , шаблон нижнего листа используется для отображения предварительного просмотра нижнего листа, который можно развернуть для получения дополнительной информации. Этого можно достичь с помощью нижнего листа библиотеки поддержки проектирования, установив свернутый размер представления с помощью setPeekHeight()
. Если вы хотите показать более короткую версию нижнего листа, вы можете установить для BottomSheetBehavior
значение STATE_COLLAPSED
.
1
2
|
mBottomSheetBehavior.setPeekHeight(300);
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
Если щелкнуть среднюю кнопку, вы получите нижний лист в режиме просмотра, который можно растянуть до полной высоты, перетащив его вверх.
Вы можете заметить, что, когда вы пытаетесь перетащить нижний лист вниз, он сворачивается только до размера, который вы видите. Вы можете решить эту проблему, добавив BottomSheetCallback
к BottomSheetBehavior
, установив размер просмотра равным нулю, когда пользователь сворачивает лист. В примере приложения это добавляется в конце onCreate()
.
01
02
03
04
05
06
07
08
09
10
11
12
|
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
mBottomSheetBehavior.setPeekHeight(0);
}
}
@Override
public void onSlide(View bottomSheet, float slideOffset) {
}
});
|
4. Использование фрагмента нижнего листа
Как я упоминал ранее в этой статье, вы также можете отобразить BottomSheetDialogFragment
вместо View
в нижнем листе. Для этого сначала нужно создать новый класс, который расширяет BottomSheetDialogFragment
.
В setupDialog()
вы можете накачать новый файл макета и получить BottomSheetBehavior
представления контейнера в вашем Activity
. Если у вас есть такое поведение, вы можете создать и связать с ним BottomSheetCallback
чтобы отклонить Fragment
когда лист скрыт.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public class TutsPlusBottomSheetDialogFragment extends BottomSheetDialogFragment {
private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
};
@Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
View contentView = View.inflate(getContext(), R.layout.fragment_bottom_sheet, null);
dialog.setContentView(contentView);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent()).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
if( behavior != null && behavior instanceof BottomSheetBehavior ) {
((BottomSheetBehavior) behavior).setBottomSheetCallback(mBottomSheetBehaviorCallback);
}
}
}
|
Наконец, вы можете вызвать show()
для экземпляра вашего Fragment
чтобы отобразить его на нижнем листе.
1
2
|
BottomSheetDialogFragment bottomSheetDialogFragment = new TutsPlusBottomSheetDialogFragment();
bottomSheetDialogFragment.show(getSupportFragmentManager(), bottomSheetDialogFragment.getTag());
|
Вывод
Использование библиотеки поддержки дизайна для отображения нижнего листа универсально и просто. Они могут использоваться для отображения деталей или сборщиков, не DialogFragment
, а также DialogFragment
отличной заменой DialogFragment
в соответствующей ситуации. Понимание того, как нижний лист можно использовать в вашем приложении, даст вам дополнительный инструмент для создания отличных приложений.