ScrollView 中 ConstraintLayout 的奇怪行为

Strange behavior of ConstraintLayout in ScrollView

我使用的是最新版本的constraint layout(1.0.2),遇到过此类问题(如下截图):

如您所见,布局已从底部裁剪掉。此问题仅出现在 ScrollView 中,或者当我尝试将 ConstraintLayout 用作 RecyclerView 中的项目时:

在这两个示例中,ConstraintLayout 的 layout_height 为 wrap_content(首先是因为 ScrollView,其次 - 我只是需要它)。我在 ScrollView 中尝试了 android:fillViewport="true",但它不起作用。我该如何解决这个问题?

布局:

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="@android:color/white"
    android:orientation="vertical">

    <include
        android:id="@+id/toolbar"
        layout="@layout/widget_toolbar"/>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">

        <android.support.constraint.ConstraintLayout
            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="wrap_content"
            android:paddingBottom="8dp"
            android:paddingTop="16dp">

            <de.hdodenhof.circleimageview.CircleImageView
                android:id="@+id/iv_edit_profile_avatar"
                android:layout_width="110dp"
                android:layout_height="110dp"
                android:contentDescription="@string/cd_avatar"
                android:src="@drawable/ic_avatar_normal"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.498"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintStart_toStartOf="parent"/>

            <TextView
                android:id="@+id/tv_edit_profile_photo_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="32dp"
                android:fontFamily="@font/font_regular"
                android:padding="8dp"
                android:text="@string/edit_profile_photo_label"
                android:textColor="@color/colorAccent"
                android:textSize="14sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/iv_edit_profile_avatar"/>

            <TextView
                android:id="@+id/tv_edit_profile_name_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:fontFamily="@font/font_regular"
                android:text="@string/edit_profile_name_label"
                android:textColor="@color/colorSecondaryText"
                android:textSize="14sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_edit_profile_photo_label"/>

            <EditText
                android:id="@+id/et_edit_profile_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="@dimen/_90sdp"
                android:fontFamily="@font/font_regular"
                android:imeOptions="actionNext"
                android:inputType="textPersonName"
                android:maxLength="25"
                android:textColor="@color/colorPrimaryText"
                android:textSize="14sp"
                app:layout_constraintBottom_toBottomOf="@+id/tv_edit_profile_name_label"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/tv_edit_profile_name_label"
                tools:text="Name"/>

            <View
                android:id="@+id/view"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="16dp"
                android:layout_marginTop="@dimen/_4sdp"
                android:background="@color/colorStroke"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/et_edit_profile_name"/>

            <TextView
                android:id="@+id/tv_edit_profile_username_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:fontFamily="@font/font_regular"
                android:text="@string/all_username_label"
                android:textColor="@color/colorSecondaryText"
                android:textSize="14sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/view"/>

            <EditText
                android:id="@+id/et_edit_profile_username"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="@dimen/_90sdp"
                android:drawableEnd="@drawable/ic_correct"
                android:fontFamily="@font/font_regular"
                android:imeOptions="actionNext"
                android:inputType="textPersonName"
                android:maxLength="20"
                android:textColor="@color/colorPrimaryText"
                android:textSize="14sp"
                app:layout_constraintBottom_toBottomOf="@+id/tv_edit_profile_username_label"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/tv_edit_profile_username_label"
                tools:text="Username"/>

            <View
                android:id="@+id/view2"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="16dp"
                android:layout_marginTop="@dimen/_4sdp"
                android:background="@color/colorStroke"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/et_edit_profile_username"/>

            <TextView
                android:id="@+id/tv_edit_profile_bio_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:fontFamily="@font/font_regular"
                android:text="@string/edit_profile_bio_label"
                android:textColor="@color/colorSecondaryText"
                android:textSize="14sp"
                app:layout_constraintBottom_toBottomOf="@+id/et_edit_profile_bio"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="@+id/et_edit_profile_bio"/>

            <EditText
                android:id="@+id/et_edit_profile_bio"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="@dimen/_90sdp"
                android:layout_marginTop="16dp"
                android:capitalize="sentences"
                android:fontFamily="@font/font_regular"
                android:imeOptions="actionNone"
                android:inputType="textMultiLine|textCapSentences"
                android:maxLines="5"
                android:textColor="@color/colorPrimaryText"
                android:textSize="14sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/view2"
                tools:text="Bioa lnmgkjn \n gkdnfmk.g .kfm kfmn mmhh lkm hklgk mngk \n nmgk mnkgnmh kjgnmh kgjnm hkgnm"/>

            <View
                android:id="@+id/view3"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="16dp"
                android:layout_marginTop="@dimen/_4sdp"
                android:background="@color/colorStroke"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/et_edit_profile_bio"/>

            <FrameLayout
                android:id="@+id/block_car_add_location"
                android:layout_width="match_parent"
                android:layout_height="@dimen/_40sdp"
                android:paddingEnd="16dp"
                android:paddingStart="16dp"
                app:layout_constraintTop_toBottomOf="@+id/view3">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:fontFamily="@font/font_regular"
                    android:text="@string/add_car_location"
                    android:textSize="14sp"/>

                <TextView
                    android:id="@+id/tv_car_location"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:layout_marginEnd="32dp"
                    android:layout_marginStart="@dimen/_76sdp"
                    android:fontFamily="@font/font_regular"
                    android:maxLength="25"
                    android:singleLine="true"
                    android:textColor="@color/colorPrimaryText"
                    android:textSize="14sp"/>

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical|end"
                    android:contentDescription="@string/cd_arrow"
                    android:src="@drawable/ic_arrow_right"/>

                <View
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
                    android:layout_gravity="bottom"
                    android:background="@color/colorStroke"/>
            </FrameLayout>

            <TextView
                android:id="@+id/tv_edit_profile_currency_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:fontFamily="@font/font_regular"
                android:text="@string/edit_profile_currency_label"
                android:textColor="@color/colorSecondaryText"
                android:textSize="14sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/block_car_add_location"/>

            <EditText
                android:id="@+id/et_edit_profile_currency"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="@dimen/_90sdp"
                android:ems="12"
                android:fontFamily="@font/font_regular"
                android:inputType="text"
                android:maxLength="3"
                android:text="@string/all_currency_usd"
                android:textSize="14sp"
                app:layout_constraintBottom_toBottomOf="@+id/tv_edit_profile_currency_label"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/tv_edit_profile_currency_label"/>

            <View
                android:id="@+id/view4"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="16dp"
                android:layout_marginTop="@dimen/_4sdp"
                android:background="@color/colorStroke"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/et_edit_profile_currency"/>

            <TextView
                android:id="@+id/tv_edit_profile_mileage_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:fontFamily="@font/font_regular"
                android:text="@string/edit_profile_mileage_label"
                android:textColor="@color/colorSecondaryText"
                android:textSize="14sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/view4"/>

            <Spinner
                android:id="@+id/spinner_edit_profile_mileage"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/_90sdp"
                android:fontFamily="@font/font_regular"
                android:paddingEnd="0dp"
                android:paddingStart="0dp"
                android:prompt="@string/all_mileage_km"
                app:layout_constraintBottom_toBottomOf="@+id/tv_edit_profile_mileage_label"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="@+id/tv_edit_profile_mileage_label"/>

            <View
                android:id="@+id/view5"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="16dp"
                android:layout_marginTop="@dimen/_4sdp"
                android:background="@color/colorStroke"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/spinner_edit_profile_mileage"/>

            <FrameLayout
                android:id="@+id/tv_edit_profile_password"
                android:layout_width="match_parent"
                android:layout_height="@dimen/_40sdp"
                android:paddingEnd="16dp"
                android:paddingStart="16dp"
                app:layout_constraintTop_toBottomOf="@+id/view5">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="16dp"
                    android:fontFamily="@font/font_regular"
                    android:text="@string/edit_profile_change_pass_label"
                    android:textColor="@color/colorAccent"
                    android:textSize="14sp"/>

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical|end"
                    android:contentDescription="@string/cd_arrow"
                    android:src="@drawable/ic_arrow_right"/>

                <View
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
                    android:layout_gravity="bottom"
                    android:background="@color/colorStroke"/>
            </FrameLayout>


            <FrameLayout
                android:id="@+id/tv_edit_profile_logout"
                android:layout_width="match_parent"
                android:layout_height="@dimen/_40sdp"
                android:paddingEnd="16dp"
                android:paddingStart="16dp"
                app:layout_constraintTop_toBottomOf="@+id/tv_edit_profile_password">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="16dp"
                    android:fontFamily="@font/font_regular"
                    android:text="@string/edit_profile_change_logout_label"
                    android:textColor="@color/colorAccent"
                    android:textSize="14sp"/>

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical|end"
                    android:contentDescription="@string/cd_arrow"
                    android:src="@drawable/ic_arrow_right"/>

                <View
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
                    android:layout_gravity="bottom"
                    android:background="@color/colorStroke"/>
            </FrameLayout>

            <TextView
                android:id="@+id/tv_edit_profile_details_label"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:background="@color/colorStroke"
                android:fontFamily="@font/font_regular"
                android:paddingBottom="12dp"
                android:paddingEnd="0dp"
                android:paddingStart="16dp"
                android:paddingTop="12dp"
                android:text="@string/edit_profile_details_label"
                android:textColor="@color/colorSecondaryText"
                android:textSize="14sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_edit_profile_logout"/>

            <TextView
                android:id="@+id/tv_edit_profile_email_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:fontFamily="@font/font_regular"
                android:text="@string/all_email_label"
                android:textColor="@color/colorSecondaryText"
                android:textSize="14sp"
                app:layout_constraintBottom_toBottomOf="@+id/et_edit_profile_email"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="@+id/et_edit_profile_email"/>

            <EditText
                android:id="@+id/et_edit_profile_email"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="@dimen/_90sdp"
                android:layout_marginTop="16dp"
                android:fontFamily="@font/font_regular"
                android:inputType="textEmailAddress"
                android:maxLength="200"
                android:textColor="@color/colorPrimaryText"
                android:textSize="14sp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_edit_profile_details_label"
                tools:text="some@mail.com"/>

            <View
                android:id="@+id/view7"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="16dp"
                android:layout_marginTop="@dimen/_4sdp"
                android:background="@color/colorStroke"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/et_edit_profile_email"/>

            <TextView
                android:id="@+id/tv_edit_profile_phone_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:fontFamily="@font/font_regular"
                android:text="@string/all_phone_label"
                android:textColor="@color/colorSecondaryText"
                android:textSize="14sp"
                app:layout_constraintBottom_toBottomOf="@+id/et_edit_profile_phone"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="@+id/et_edit_profile_phone"/>

            <EditText
                android:id="@+id/et_edit_profile_phone"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="@dimen/_90sdp"
                android:layout_marginTop="16dp"
                android:fontFamily="@font/font_regular"
                android:inputType="phone"
                android:maxLength="17"
                android:textColor="@color/colorPrimaryText"
                android:textSize="14sp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/et_edit_profile_email"
                tools:text="+38 066 249 52 76"/>

            <View
                android:id="@+id/view8"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginEnd="16dp"
                android:layout_marginStart="16dp"
                android:layout_marginTop="@dimen/_4sdp"
                android:background="@color/colorStroke"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/et_edit_profile_phone"/>

            <TextView
                android:id="@+id/tv_edit_profile_remove_acc_label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:fontFamily="@font/font_regular"
                android:text="@string/edit_profile_remove_acc_label"
                android:textColor="@color/colorPrimaryText"
                android:textSize="12sp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/view8"/>

            <Button
                android:id="@+id/but_edit_profile_delete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="16dp"
                android:width="@dimen/_64sdp"
                android:height="@dimen/_24sdp"
                android:background="@drawable/shape_gray_stroked"
                android:fontFamily="@font/font_bold"
                android:minHeight="@dimen/_24sdp"
                android:minWidth="@dimen/_64sdp"
                android:padding="0dp"
                android:text="@string/all_delete_but"
                android:textAllCaps="false"
                app:layout_constraintBottom_toBottomOf="@+id/tv_edit_profile_remove_acc_label"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="@+id/tv_edit_profile_remove_acc_label"/>

        </android.support.constraint.ConstraintLayout>
    </ScrollView>
</LinearLayout>

您的 Button 底部受 TextView 底部限制。与View android:id="@+id/view8"的底部进一步匹配。但是你View的bottom跟bottom不匹配。我在 recyclerview 中遇到了同样的问题,最后 child 的底部与 parent 约束布局不匹配。试试这个:

<TextView
    android:id="@+id/tv_edit_profile_remove_acc_label"
    android:layout_width="wrap_content"
    android:layout_height="0dp"
    android:layout_marginStart="16dp"
    android:layout_marginTop="16dp"
    android:fontFamily="@font/font_regular"
    android:text="@string/edit_profile_remove_acc_label"
    android:textColor="@color/colorPrimaryText"
    android:textSize="12sp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/view8"
    app:layout_constraintBottom_toBottomOf="parent"/>

祝你好运:D