Заполнение строки состояния CoordinatorLayout исчезает со второй страницы ViewPager

EDIT от 02.01.2016: ошибка должна быть устранена путем применения кода, предоставленного командой Android: https://stackoverflow.com/a/35132144/3397345, см. принятый ответ ниже.

EDIT от 27/01/2016: Ошибка до сих пор не устранена в версии 23.1.1. Решения, предоставленные до сих пор, не дают прозрачной строки состояния (что является целью этого макета) или слишком сложны. Новая запись экрана с ошибкой доступна здесь: https://www.youtube.com/watch?v=76IxhlUx8MQ

EDIT от 23/07/2015: Support Design Library v22.2.1 не исправлена ​​:-( Также это происходит при быстром возврате панели инструментов на MainActivity!

EDIT от 28/07/2015: Связанный вопрос: Заполнение строки состояния CoordinatorLayout исчезает во время транзакций фрагментов

Из примера репозитория https://github.com/chrisbanes/cheesesquare я реализовал ViewPager on Detail Мероприятия. Это работает, но строка состояния исчезает со 2-й страницы, как вы видите на картинке только на устройствах Lollipop. Есть идеи? Я использую android:fitsSystemWindows="true", но он работает только на первой странице :-(

введите здесь описание изображения

activity_detail_viewpager.xml, если я помещу сюда fitsSystemWindows, панель состояния больше не будет прозрачной, но она будет работать (заполнение строки состояния не потеряется). Но хотелось бы прозрачного!

<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.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="ifContentScrolls"/>

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

activity_detail_fragment.xml

<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:layout_width="match_parent"
        android:layout_height="@dimen/detail_backdrop_height"
        android:fitsSystemWindows="true"
        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="match_parent"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleMarginEnd="64dp">

            <ImageView
                android:id="@+id/back_item"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" />

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

    <android.support.v4.widget.NestedScrollView
        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">

            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/card_margin">

                ...

            </android.support.v7.widget.CardView>

            ...

        </LinearLayout>

    </android.support.v4.widget.NestedScrollView>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        android:clickable="true"
        android:src="@drawable/ic_discuss"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|end"
        app:borderWidth="0dp"/>

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

style.xml v21

<resources>
    <style name="AppTheme" parent="AppTheme.Base">
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

comment
Сообщение о проблеме в Google: code.google.com/p/android/issues. /detail?id=180492 — Проблема подтверждена и другими пользователями.   -  person Davideas    schedule 28.07.2015


Ответы (4)


Решение, предложенное командой Android в ответ на мой заявленный дефект. Этот код должен, наконец, работать.

ViewPager mViewPager;

ViewCompat.setOnApplyWindowInsetsListener(mViewPager,
        new OnApplyWindowInsetsListener() {
    @Override
    public WindowInsetsCompat onApplyWindowInsets(View v,
            WindowInsetsCompat insets) {
        insets = ViewCompat.onApplyWindowInsets(v, insets);
        if (insets.isConsumed()) {
            return insets;
        }

        boolean consumed = false;
        for (int i = 0, count = mViewPager.getChildCount(); i <  count; i++) {
            ViewCompat.dispatchApplyWindowInsets(mViewPager.getChildAt(i), insets);
            if (insets.isConsumed()) {
                consumed = true;
            }
        }
        return consumed ? insets.consumeSystemWindowInsets() : insets;
    }
});
person Davideas    schedule 01.02.2016
comment
Три года спустя в этом вопросе все еще происходит. Знаете ли вы какую-нибудь тему, в которой Google обсуждал эту проблему? Кстати, отличное решение! - person rewgoes; 08.08.2019

Как и sidecarcat, я столкнулся с похожей проблемой (используя v23.1.1). Я публикую здесь обходной путь, используя код sidecarcat, и добавляю код для удаления лишнего заполнения в некоторых случаях.

    // in onCreateView: adjust toolbar padding
    final int initialToolbarHeight = mToolbar.getLayoutParams().height;
    final int initialStatusBarHeight = getStatusBarHeight();
    mToolbar.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            int[] locToolbar = new int[2];
            mToolbar.getLocationOnScreen(locToolbar);
            int yToolbar = locToolbar[1];
            int topPaddingToolbar = mToolbar.getPaddingTop();
            if (isAdded()) {
                //normal case : system status bar padding on toolbar : yToolbar = initialStatusBarHeight && topPaddingToolbar = 0
                //abnormal case : no system status bar padding on toolbar -> toolbar behind status bar => add custom padding
                if (yToolbar != initialStatusBarHeight && topPaddingToolbar == 0) {
                    mToolbar.setPadding(0, initialStatusBarHeight, 0, 0);
                    mToolbar.getLayoutParams().height = initialToolbarHeight + initialStatusBarHeight;
                }
                //abnormal case : system status bar padding and custom padding on toolbar -> toolbar with padding too large => remove custom padding
                else if (yToolbar == initialStatusBarHeight && topPaddingToolbar == initialStatusBarHeight) {
                    mToolbar.setPadding(0, 0, 0, 0);
                    mToolbar.getLayoutParams().height = initialToolbarHeight;
                }
            }
        }
    });

    return mRootView;
}

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}
person faves    schedule 06.01.2016

Я столкнулся с похожей проблемой (используя v23.0.1). В моем случае проблема возникает и на первой странице. Обходной путь, на котором я остановился, заключался в настройке отступов и высоты панели инструментов при создании фрагмента.

    // in onCreateView: adjust toolbar padding
    Toolbar toolbar = (Toolbar) mRootView.findViewById(R.id.toolbar);
    toolbar.setPadding(0, getStatusBarHeight(), 0, 0);
    toolbar.getLayoutParams().height = toolbar.getLayoutParams().height + getStatusBarHeight();

    return mRootView;
}

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}
person sidecarcat    schedule 06.10.2015
comment
Хорошо, это начало, и что-то начинает работать (как исправление), но при прокрутке влево и вправо на некоторых страницах это заполнение становится излишним, есть ли способ узнать, стало ли заполнение строки состояния снова видимым, так что чтобы не добавлять высоту строки состояния? Мы должны получить реальную высоту строки состояния. Наверное. - person Davideas; 22.10.2015

Кажется, решение для этого простое

У вас есть

android:fitsSystemWindows="true"

Во фрагменте CoordinateLayoutView

удалите его отсюда и поместите в корневой вид Activity.

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

person RuAware    schedule 06.11.2015
comment
Здравствуйте, цель состоит в том, чтобы сделать его прозрачным, поэтому это решение не может быть принято. Я думаю, что библиотека дизайна работает для обычных и простых случаев, в то время как у нее есть большие проблемы (и не только это, описанное в моем вопросе) в сложных случаях. Я почти готов отказаться от этой библиотеки в случае просмотра пейджера. - person Davideas; 23.12.2015
comment
пожалуйста, покажите мне код, у меня прозрачная/цветная строка состояния, если это изображение в googlecode, то похоже, что у вас может быть android:fitsSystemWindows=true в нескольких местах - person RuAware; 24.12.2015