当将fitsSystemWindows设置为true时,CollapsingToolbarLayout中的ViewGroup显示额外的底部填充

Ant*_*eef 8 android android-layout

我正在构建一个应用程序,并且有一个配置文件片段,显示配置文件背景图像和一些其他元素.如下面的截图:

在此输入图像描述

我的问题是:为什么AppBarLayout结束时会有额外的底部填充?

这是这个片段的xml布局文件(我基本上是从Cheesesquare复制的):

<android.support.design.widget.CoordinatorLayout
    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.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        >

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:contentScrim="@android:color/white"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            >

            <android.support.constraint.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fitsSystemWindows="true"
                >

                <ImageView
                    android:id="@+id/profile_bg"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/height_profile_background_max"
                    android:scaleType="centerCrop"
                    android:fitsSystemWindows="true"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    />

                <de.hdodenhof.circleimageview.CircleImageView
                    android:id="@id/avatar"
                    android:layout_width="@dimen/avatar_size_large"
                    android:layout_height="@dimen/avatar_size_large"
                    android:layout_marginStart="@dimen/horizontal_padding_normal"
                    app:civ_border_width="2dp"
                    app:civ_border_color="@android:color/white"
                    app:civ_border_overlay="false"
                    app:layout_constraintTop_toBottomOf="@id/profile_bg"
                    app:layout_constraintBottom_toBottomOf="@id/profile_bg"
                    app:layout_constraintStart_toStartOf="parent"
                    />

                <TextView
                    android:id="@id/user_display_name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:paddingTop="@dimen/vertical_padding_small"
                    android:layout_marginStart="@dimen/horizontal_padding_normal"
                    android:textSize="@dimen/text_size_medium"
                    android:textStyle="bold"
                    android:textColor="@color/text_color_normal"
                    app:layout_constraintTop_toBottomOf="@id/avatar"
                    app:layout_constraintStart_toStartOf="parent"
                    />

                <TextView
                    android:id="@+id/description"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:paddingTop="@dimen/vertical_padding_small"
                    android:paddingBottom="@dimen/vertical_padding_normal"
                    android:layout_marginStart="@dimen/horizontal_padding_normal"
                    android:textSize="@dimen/text_size_small"
                    android:textColor="@color/text_color_normal"
                    android:maxLines="5"
                    app:layout_constraintTop_toBottomOf="@id/user_display_name"
                    app:layout_constraintStart_toStartOf="parent"
                    />

                <View
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/vertical_divider_height"
                    android:background="@color/divider_background_color"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintBottom_toBottomOf="parent"
                    />
            </android.support.constraint.ConstraintLayout>

            <android.support.v7.widget.Toolbar
                android:id="@id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:contentInsetStartWithNavigation="0dp"
                app:layout_collapseMode="pin"
                />
        </android.support.design.widget.CollapsingToolbarLayout>

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

    <android.support.v7.widget.RecyclerView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        android:scrollbarSize="2dp"
        android:scrollbarStyle="outsideOverlay"
        app:layoutManager="LinearLayoutManager"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        />

</android.support.design.widget.CoordinatorLayout>
Run Code Online (Sandbox Code Playgroud)

如上所示,我没有添加任何填充AppBarLayout.

我将我的布局与Cheesesquare进行比较,发现唯一不同的是我ConstraintLayout在AppBarLayout中放置了一个复合体.Cheesesquare表现正常,因为它设置layout_height了某个值:

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="@dimen/detail_backdrop_height"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:fitsSystemWindows="true">
Run Code Online (Sandbox Code Playgroud)

我正在设置我layout_height的AppBarLayout wrap_content,因为self intro标题中的部分可能是很多单词,应该是wrap_content确保每个句子都能显示在屏幕上.

我想知道为什么这个额外的填充出现了?还有,我发现这个额外填充的高度似乎与statusBar的高度相同.它看起来像是与fitsSystemWindow属性相关的东西.如果有人能告诉我如何删除这个烦人的底部填充,那将是很好的.

ps:我也尝试了其他一些ViewGroup布局,LinearLayout或者Framelayout对于这个区域,它们都是一样的,所以我很确定它与ConstraintLayout我使用无关.

abn*_*ner 7

此问题可能是由此提交引起的

我用@Bogdan Zurac的评论方式以编程方式修复了它.

mCollapseContentLy = findViewById(R.id.ly_collapse_content);
mCollapseContentLy.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        int measuredHeight = mCollapseContentLy.getMeasuredHeight();
        ViewGroup.LayoutParams lp = mCollapsingToolbarLayout.getLayoutParams();
        layoutParams.height = measuredHeight;
        mCollapsingToolbarLayout.setLayoutParams(lp);
        mCollapseContentLy.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }
});
Run Code Online (Sandbox Code Playgroud)

接受后编辑

创建一个新的类扩展CollapsingToolbarLayout并覆盖该onMeasure方法

package android.support.design.widget;

import android.content.Context;
import android.util.AttributeSet;

public class GodCollapsingToolbarLayout extends CollapsingToolbarLayout {

    public GodCollapsingToolbarLayout(Context context) {
        this(context, null);
    }

    public GodCollapsingToolbarLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        final int mode = MeasureSpec.getMode(heightMeasureSpec);
        final int topInset = mLastInsets != null ? mLastInsets.getSystemWindowInsetTop() : 0;
        if (mode == MeasureSpec.UNSPECIFIED && topInset > 0) {
            // fix the bottom empty padding
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(
                    getMeasuredHeight() - topInset, MeasureSpec.EXACTLY);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • mLastInsets在哪里? (3认同)

use*_*413 7

根据@Akshay 的回答,这是我的解决方案:

在 xml 文件中添加 android:fitsSystemWindows="true" 到:

  1. 协调器布局
  2. 应用栏布局
  3. ImageView(或您想在状态栏后面看到的其他视图。在我的情况下,它是一个 ConstraintLayout)

在活动中添加@Akshay 答案但按如下方式编辑(用 Kotlin 编写):

 ViewCompat.setOnApplyWindowInsetsListener(appBarLayout) { _, insets ->
        // Instead of
        // toolbar.setPadding(0, insets.systemWindowInsetTop, 0, 0)
        (toolbar.layoutParams as ViewGroup.MarginLayoutParams).topMargin = insets.systemWindowInsetTop
        insets.consumeSystemWindowInsets()
    }
Run Code Online (Sandbox Code Playgroud)

现在工具栏也将具有适当的高度。