Как применить вставки к CollapsingToolbarLayout с изображением внутри, чтобы изображение на панели инструментов отображалось за строкой состояния?
Я пытаюсь настроить полноэкранную активность для Android 10 с помощью вставок. Я хотел, чтобы изображение на панели инструментов отображалось за строкой состояния. Я пытался использоватьandroid:fitsSystemWindows
флаг в разных комбинациях, но не работает, AppBarLayout
не имеет правильного заполнения, а строка состояния слегка перекрывает элементы управления меню панели инструментов. Итак, я использовал удобныйWindowInsetsCompat
wrapper, библиотека Insetter от Chris Banes, для установки отступов в соответствии с вставками системного окна.
Вот мой макет:
<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:id="@+id/book_activity_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
tools:context="com.bookcrossing.mobile.ui.bookpreview.BookActivity"
>
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
...
</androidx.core.widget.NestedScrollView>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/toolbarContainer"
android:layout_width="match_parent"
android:layout_height="220dp"
>
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleGravity="bottom"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:titleEnabled="true"
app:toolbarId="@id/toolbar"
>
<ImageView
android:id="@+id/cover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/cover_description"
android:scaleType="centerCrop"
android:cropToPadding="true"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.5"
/>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways"
tools:title="War and Peace"
/>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/default_padding"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_turned_in_not_white_24dp"
app:layout_anchor="@id/toolbar_container"
app:layout_anchorGravity="bottom|right|end"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Вот как я устанавливаю отступы в коде:
Insetter.setOnApplyInsetsListener(toolbarContainer, (view, windowInsets, initial) -> {
view.setPadding(initial.getPaddings().getLeft(),
windowInsets.getSystemWindowInsetTop() + initial.getPaddings().getTop(),
initial.getPaddings().getRight(), initial.getPaddings().getBottom());
});
Insetter.setOnApplyInsetsListener(cover, (view, windowInsets, initial) -> {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
params.topMargin = windowInsets.getSystemWindowInsetTop() + initial.getMargins().getTop();
view.setLayoutParams(params);
});
Insetter.setOnApplyInsetsListener(nestedScrollView, (view, windowInsets, initial) -> {
view.setPadding(initial.getPaddings().getLeft(), initial.getPaddings().getTop(),
initial.getPaddings().getRight(),
windowInsets.getSystemWindowInsetBottom() + initial.getPaddings().getBottom());
});
Insetter.setOnApplyInsetsListener(favorite, (view, windowInsets, initialPadding) -> {
view.setPadding(initialPadding.getPaddings().getLeft(), initialPadding.getPaddings().getTop(),
windowInsets.getSystemWindowInsetRight() + initialPadding.getPaddings().getRight(),
initialPadding.getPaddings().getBottom());
});
Я установил оконные флаги для полноэкранного режима:
root.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
И вот результат:
Строка состояния настроена на прозрачность, синий цвет - это панель инструментов с верхним отступом.
В конечном итоге я бы хотел, чтобы изображение отображалось за строкой состояния, возможно ли это вообще?
Тестирую на эмуляторе Android 10.
3 ответа
Ваши флаги кажутся неправильными. Вы устанавливаете флаг для панели навигации, в то время как вы должны устанавливать флаг для строки состояния.
Вот код, который я использую (Котлин):
requireActivity().window?.decorView?.systemUiVisibility = (
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
чтобы пользовательский интерфейс отображался за строкой состояния без скрытия строки состояния. Затем я использую эту функцию расширения, которую использую для представлений, которые не должны перекрываться со строкой состояния, например с кнопками и другими элементами управления:
fun View.alignBelowStatusBar() {
this.setOnApplyWindowInsetsListener { view, insets ->
val params = view.layoutParams as ViewGroup.MarginLayoutParams
params.topMargin = insets.systemWindowInsetTop
view.layoutParams = params
insets
}
}
Таким образом, первые флаги гарантируют, что ваши фоны / изображения будут находиться под строкой состояния. Второй - убедиться, что элементы управления не перекрываются строкой состояния.
Насколько я помню, вам не нужно поддерживать отступы в CoordinatorLayout вручную, см. setupForInsets
функционировать в CoordinatorLayout
класс. Для поддержки рисования за строкой состояния вы должны установитьandroid:fitsSystemWindows="true"
за CoordinatorLayout
:
<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:id="@+id/book_activity_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
tools:context="com.bookcrossing.mobile.ui.bookpreview.BookActivity"
>
И как я понимаю вам не нужно animateLayoutChanges
Вот. Он отвечает за анимацию при изменении макета, например, удаление / добавление и отображение / скрытие представлений.