Использование windowTranslucentStatus с CollapsingToolbarLayout

Я пытаюсь получить эффект, аналогичный тому, что можно увидеть в Google Play.

У меня есть макет ниже, чтобы показать прозрачную панель инструментов с изображением за ней. Когда пользователь прокручивает изображение, возникает эффект параллакса, когда он прокручивается за пределы экрана. Панель инструментов возвращается всякий раз, когда пользователь прокручивает вверх, а изображение возвращается только тогда, когда пользователь доходит до конца списка.

Все это отлично работает.

<android.support.design.widget.CoordinatorLayout
    android:id="@+id/main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:background="@color/background_material_dark">
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:minHeight="?attr/actionBarSize"
            app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
            app:statusBarScrim="#09b"
            app:contentScrim="#09f">
            <ImageView
                android:id="@+id/img"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:src="@drawable/location_banner"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7"
                />
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_height="?attr/actionBarSize"
                android:layout_width="match_parent"
                app:layout_collapseMode="pin"
                android:fitsSystemWindows="true"
                app:theme="@style/ThemeOverlay.AppCompat.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"/>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

</android.support.design.widget.CoordinatorLayout>

Проблема

Когда я устанавливаю для windowTranslucentStatus значение true. Содержимое в представлении перемещается вверх, чтобы оказаться под строкой состояния, но содержимое CollapsingToolbarLayout перемещается вверх в два раза по высоте строки состояния (CollapsingToolbarLayout сохраняет правильную высоту).

Это означает, что часть верхней части изображения обрезана, и панель действий теперь отображается под строкой состояния, а не под ней. В качестве побочного эффекта теперь в нижней части CollapsingToolbarLayout есть отступ той же высоты, что и строка состояния.

Вот как это выглядит без окнаTranslucentStatus. Здесь все работает нормально введите здесь описание изображения

Для windowTranslucentStatus установлено значение true введите здесь описание изображения

Пользователь прокручивает список снизу вверх (не сверху) введите здесь описание изображения


comment
как вы решили эту проблему. К сожалению, я получаю эту ошибку, не могли бы вы поделиться своим решением?   -  person Noundla Sandeep    schedule 03.07.2016
comment
Google ломает это каждый раз, когда выпускает новую версию библиотеки поддержки, но вы можете каждый раз находить другой хак, чтобы обойти это (очень неприятно). 23.1.1 - хорошая ставка, чтобы все работало нормально. Подробнее в предпоследнем сообщении здесь code.google.com/p/android/issues/   -  person Stimsoni    schedule 04.07.2016
comment
да, раньше (со старыми инструментами сборки) он работал нормально, если я оставил fitsSystemWindows=true. Тем не менее, он сломался в последних инструментах сборки. После долгих усилий я удалил thefitsSystemWindows из корневого макета, и теперь он работает, как и ожидалось. Спасибо за ответ :)   -  person Noundla Sandeep    schedule 05.07.2016
comment
Я заметил, что определенный paddingTop был добавлен в мой RecyclerView при использовании fitSystemWindow. В конце концов я реализовал хак, который сбрасывает paddingTop на ноль вручную в пользовательском ресайклере. Теперь он работает нормально. Не лучшее решение, но, по крайней мере, пока оно работает...   -  person TheWhiteLlama    schedule 26.09.2017


Ответы (7)


Добавьте fitsSystemWindows в макет и установите значение true.

Обновить

Извините за мой неполный ответ. Вы должны добавить fitsSystemWindows="true" в макет xml, как показано ниже.

<android.support.design.widget.CoordinatorLayout
    android:id="@+id/main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:background="@color/background_material_dark"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:minHeight="?attr/actionBarSize"
            app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
            app:statusBarScrim="#09b"
            app:contentScrim="#09f"
            android:fitsSystemWindows="true">

            <ImageView
                android:id="@+id/img"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:src="@drawable/location_banner"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7"
                android:fitsSystemWindows="true"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_height="?attr/actionBarSize"
                android:layout_width="match_parent"
                app:layout_collapseMode="pin"
                android:fitsSystemWindows="true"
                app:theme="@style/ThemeOverlay.AppCompat.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"/>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

</android.support.design.widget.CoordinatorLayout>
person David Jin Han    schedule 24.06.2015
comment
Было бы полезно опубликовать пример кода, например: fitsSystemWindows = true или что-то в этом роде. - person tvgemert; 24.06.2015
comment
Где я могу добавить это. Я провел несколько тестов с этим, и это не совсем сработало. Как вы можете видеть, он был добавлен на панель инструментов в опубликованном xml. Я обнаружил, что это добавило некоторые отступы, но только опустило панель инструментов вдвое меньше, чем ожидалось. Это также не исправило обрезание изображения. - person Stimsoni; 26.06.2015
comment
Извините за задержку с ответом. Это привело меня к большей части пути, спасибо, но все же не переместило панель инструментов вниз. Мне пришлось совместить твой ответ с ответом Генри, чтобы перебраться через черту. Для всех, кто читает, я добавил fitsSystemWindows в CoordiatorLayout, AppBarLayout и ImageView. Затем мне пришлось добавить android:layout_marginTop=-48dp (стандартная высота панели инструментов) в представление панели инструментов, как указано в ответе Генри. - person Stimsoni; 21.07.2015
comment
Я не знал, что app:statusBarScrim является свойством, пока не увидел этот ответ. Это помогло мне исправить другую ошибку, которую я обнаружил: reddit.com/r/ androiddev/comments/8xai0g/ - person toobsco42; 10.07.2018

Произошло обновление библиотеки дизайна. Я предполагаю, что проблема, описанная выше, была ошибкой.

Если вы обновите библиотеку дизайна до последней версии, эта проблема больше не возникает.

Теперь я удалил все fitsSystemWindows="true", кроме ImageView (поскольку он должен отображаться в строке состояния).

Я также удалил минусовое дополнение с панели инструментов.

Это моя тема для 21+

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowActionBarOverlay">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:textColorPrimary">@android:color/white</item>
</style>

Теперь все работает как положено

person Stimsoni    schedule 08.10.2015
comment
Извините, что наткнулся на @Stimsoni, но это полностью работает?? Для меня это работает с изображением, идущим за панелью состояния, но когда я прокручиваю содержимое вниз, чтобы отобразить панель инструментов, за панелью состояния ничего не рисуется. - person Timestretch; 25.02.2016
comment
Это звучит правильно. Когда панель инструментов возвращается в поле зрения, то же самое происходит и со строкой состояния. Если вы хотите, чтобы контент находился за панелью инструментов, но снова появлялся над ней, вы можете попробовать добавить прозрачный экран в строку состояния. Я еще не тестировал это, хотя - person Stimsoni; 25.02.2016
comment
Я люблю такие комментарии. Не работает????? Оооо..... что не работает? какие-либо ошибки? что творится? - person Stimsoni; 13.11.2018

Лучший способ добиться этого, как сказал Стимсони

Добавьте android:fitsSystemWindows="true" в CoordiatorLayout, AppBarLayout и ImageView.

<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">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appBar"
    android:fitsSystemWindows="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:contentScrim="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

        <ImageView
            android:id="@+id/background"
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:scaleType="centerCrop"
            android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax"
            android:alpha="0.75"
            android:src="@drawable/foo"/>

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_collapseMode="pin"/>
    </android.support.design.widget.CollapsingToolbarLayout>        
</android.support.design.widget.AppBarLayout>...
person mparkes    schedule 12.01.2016
comment
Это вызывало ошибку в более новой версии библиотеки ('com.android.support:design:27.1.1'), где у моего пейджера было слишком много отступов сверху. Я удалил android:fitsSystemWindows=true из макета координатора, и поведение соответствует ожидаемому. - person mparkes; 09.09.2018

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

Добавьте следующие теги в представление «android.support.v7.Widget.Toolbar»:

android:layout_height="48dp" // Whatever the height of the toolbar you want
android:layout_marginTop="-48dp" // Negative of the height of the toolbar
person Henry    schedule 30.06.2015
comment
Спасибо, Генри, мне пришлось объединить ваш ответ с ответом Дэвида, чтобы заставить это работать правильно. - person Stimsoni; 21.07.2015

Расширьте CoordinatorLayout и вызовите setOnApplyWindowInsetsListener в своем конструкторе, чтобы сбросить значения вставки. Вот код:

public class CustomCoordinatorLayout extends CoordinatorLayout {
    public CustomCoordinatorLayout(Context context) {
        super(context);
        init();
    }

    public CustomCoordinatorLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomCoordinatorLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
            setOnApplyWindowInsetsListener(new OnApplyWindowInsetsListener() {
                @Override
                public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
                    WindowInsets replaced = windowInsets.replaceSystemWindowInsets(0, 0, 0, 0);
                    return replaced;
                }
            });
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}
person Enes    schedule 23.06.2016
comment
replaceSystemWindowInsets требует API › 20 - person Simon; 21.10.2016

У меня такая же проблема, но я знаю одно.

Если вы хотите, чтобы на обычной панели инструментов была прозрачная строка состояния, вам нужно добавить верхний отступ 16dp.

person alvarlagerlof    schedule 18.06.2015
comment
Вы говорите, что для высоты панели инструментов вы не используете ?attr/actionBarSize. у вас такой рост + 16dp. Наличие этого отступа без высоты означало бы, что нижняя часть содержимого панели инструментов будет отодвинута от нижней части представления. - person Stimsoni; 19.06.2015
comment
Спасибо, в конце нам нужен paddingTop 16dp, удаление fitsSystemWindow=true из макета и активация <item name="android:windowTranslucentStatus">true</item> для работы. - person Vincent D.; 04.05.2016

Просто измените цвет строки состояния в Styles.XML(v21)

<item name="android:statusBarColor">@android:color/transparent</item>

или удалите указанную выше строку в этом XML, он отлично работает.

person Praveen Attigeri    schedule 05.08.2016