#android #android-layout #android-toolbar #android-appbarlayout
#Android #android-макет #android-панель инструментов #android-coordinatorlayout #android-appbarlayout
Вопрос:
То, что я пытаюсь реализовать, — это панель инструментов, которая не имеет полной ширины (имеет поле со всех сторон 16dp), как показано ниже:
Gmail — Обратите внимание, что RecyclerView
можно увидеть прокрутку за панелью инструментов
Приложение Google — то же самое, карточки видны за панелью инструментов.
Кроме того, эти панели инструментов скрываются при прокрутке вниз и появляются при прокрутке вверх.
Содержимое панели инструментов — это не то, о чем я беспокоюсь прямо сейчас.
Я предполагаю, что это делается с использованием макета координатора, так что это скелет, который у меня есть:
- Макет координатора
- AppBarLayout
- Панель инструментов
- Вложенный просмотр прокрутки (appbar_scrolling_view_behavior)
- ConstraintLayout
- AppBarLayout
<androidx.coordinatorlayout.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"
android:animateLayoutChanges="true"
tools:context=".MainContentFragment">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_margin="32dp"
android:background="@android:color/transparent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@android:color/holo_red_dark"
app:layout_scrollFlags="scroll|enterAlways">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
...
Это вывод перед прокруткой
И после прокрутки вниз
Как вы можете видеть, пространство за пределами панели инструментов непрозрачно, но имеет этот серый фон, поскольку содержимое находится под ним и его нельзя увидеть.
Ответ №1:
Идея отображения содержимого за панелью инструментов:
-
Установка отрицательного поля для просмотра прокрутки (
NestedScrollView
/RecyclerView
), которое соответствует желаемому размеру пустой области при прокрутке всего содержимого вверх (все, что находится под панелью инструментов, ничего позади); предполагается -100dp в приведенной ниже демонстрации -
Верните обратно это отрицательное поле для дочернего элемента
NestedScrollView
(в макете) или 1-го дочернего элементаRecyclerView
(программно) -
Поместите вид прокрутки поверх
AppBarLayout
так, чтобы фонAppBarLayout
не закрывал содержимое прокрутки, чтобы они отображались в задней части панели инструментов.
Косметика:
- Удалите значение
AppBarLayout
до 0, чтобы сделать его несуществующим; есть только панель инструментов. - Установите цвет фона
AppBarLayout
на прозрачный, так что теперь он принимает фон корневого макета.
ДЕМОНСТРАЦИЯ:
<androidx.coordinatorlayout.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"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-100dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="100dp"
android:text="@string/longText" />
</androidx.core.widget.NestedScrollView>
<com.google.android.material.appbar.AppBarLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
app:elevation="0dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="@drawable/rounded_toolbar"
app:layout_scrollFlags="scroll|enterAlways">
<com.google.android.material.appbar.MaterialToolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Для RecyclerView
вы не можете управлять его дочерними элементами с помощью макетов, поэтому изменение поля можно либо с помощью
- Имея 2 макета, один с верхним полем 100dp для первого дочернего элемента, другой без полей для остальных дочерних элементов. И решите, какой макет в адаптере
onCreateViewHolder()
- Добавление поля в поле адаптера
onBindViewHolder()
:
@Override
public void onBindViewHolder(@NonNull CustomViewHolder holder, final int position) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) holder.itemView.getLayoutParams();
if (position == 0) {
Resources resources = holder.itemView.getContext().getResources();
float dip = 100f;
float px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dip,
resources.getDisplayMetrics()
);
params.topMargin = (int) px;
} else
params.topMargin = 0;
holder.itemView.setLayoutParams(params);
//...... rest of code
}
Ответ №2:
Вы должны просто обернуть все виджеты внутри CoordinatorLayout
с помощью FrameLayout
и изменить AppBarLayout
положение до конца:
<androidx.coordinatorlayout.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"
android:animateLayoutChanges="true"
tools:context=".MainContentFragment">
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
...
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_margin="32dp"
android:background="@android:color/transparent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@android:color/holo_red_dark"
app:layout_scrollFlags="scroll|enterAlways">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
</FrameLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout