使用不带setSupportActionBar的CollapsingToolbarLayout会导致错误的折叠标题位置

时间:2018-06-29 06:45:19

标签: android android-collapsingtoolbarlayout androiddesignsupport

就像标题所述,如果在活动中使用不带setSupportActionBar的工具栏,则在工具栏折叠时,工具栏的标题将具有奇怪的顶部填充,并且该填充为24dp height,即状态栏的高度。

屏幕截图:
Collapsing issue screenshot

但是,如果我将setSupportActionBar(toolbar)添加到Activity的onCreate中,则此问题得以解决。

布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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=".ScrollingActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:toolbarId="@+id/toolbar">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                app:title="test"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

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

    <include layout="@layout/content_scrolling" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|end"
        app:srcCompat="@android:drawable/ic_dialog_email" />

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

我仅使用示例ScrollActivity进行了较大的修改,只需将一个app:title添加到工具栏,并注释掉setSupportActionBar(toolbar);

设计库的版本是27.1.1

1 个答案:

答案 0 :(得分:0)

事实上,我已经解决了这个问题,但是却不知道Google这么做的原因。

在CollapsingToolbarLayout的onLayout方法中,它将首先计算工具栏的折叠标题位置

final int maxOffset = getMaxOffsetForPinChild(
                        mToolbarDirectChild != null ? mToolbarDirectChild : mToolbar);
                ViewGroupUtils.getDescendantRect(this, mDummyView, mTmpRect);
                mCollapsingTextHelper.setCollapsedBounds(
                        mTmpRect.left + (isRtl
                                ? mToolbar.getTitleMarginEnd()
                                : mToolbar.getTitleMarginStart()),
                        mTmpRect.top + maxOffset + mToolbar.getTitleMarginTop(),
                        mTmpRect.right + (isRtl
                                ? mToolbar.getTitleMarginStart()
                                : mToolbar.getTitleMarginEnd()),
                        mTmpRect.bottom + maxOffset - mToolbar.getTitleMarginBottom());

,maxOffset在getMaxOffsetForPinChild处计算,如下所示:

final int getMaxOffsetForPinChild(View child) {
    final ViewOffsetHelper offsetHelper = getViewOffsetHelper(child);
    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
    return getHeight()
            - offsetHelper.getLayoutTop()
            - child.getHeight()
            - lp.bottomMargin;
}

问题是,offsetHelper.getLayoutTop()将首先返回0而不是真正的前24dp,因为此时尚未调用offsetHelper的onViewLayout,它将在计算折叠的标题位置后被调用。

    // Update our child view offset helpers. This needs to be done after the title has been
    // setup, so that any Toolbars are in their original position
    for (int i = 0, z = getChildCount(); i < z; i++) {
        getViewOffsetHelper(getChildAt(i)).onViewLayout();
    }

根据评论,这是预期的行为,必须在设置标题后调用onViewLayout。这是我不明白的地方。

我想setSupportActionBar做了一些使onLayout再次被调用的操作,这将使用正确的LayoutTop重新计算标题的位置。所以我添加以下代码:

    final CollapsingToolbarLayout v = findViewById(R.id.toolbar_layout);
    v.post(new Runnable() {
        @Override
        public void run() {
            v.requestLayout();
        }
    });

进入活动的onCreate方法,并解决了问题。

现在,我将这个问题悬而未决,因为我认为这不是一个优雅的解决方案,也许有一些官方方法可以解决此问题。还是这是Android开发人员不知道的错误?