如何在滚动视图中制作嵌套约束布局以匹配主父布局的大小

How to make a nested constraint layout inside scrollview to match the size of main parent layout

编辑:我想要的是用两个按钮制作底部的红色部分,当屏幕尺寸大于 6.3 时,底部的整个 space 与顶部保持 88dp 的边距。 现在发生了什么:红色背景直到底部才占据 space(见屏幕截图)。我找不到使约束布局展开的方法 我想使 scrollView 内的底部约束布局与父布局大小相匹配,而不从底部创建任何间隙。这只发生在 6.3 和更高的屏幕尺寸

Sceenshot

我尝试只取出底部约束布局和两个按钮。它在一定程度上解决了问题但是它使小屏幕尺寸下的视图更难看

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="match_parent"
    android:background="@drawable/ic_background"
    tools:context=".presentation.offers.OfferDetailsActiviy">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar_offer_details"
        style="@style/AppToolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:contentInsetStart="10dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:titleTextAppearance="@style/ToolbarTextAppearance.Title" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar_offer_details">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <androidx.cardview.widget.CardView
                android:id="@+id/cardView_offer_details"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="20dp"
                android:layout_marginTop="20dp"
                android:layout_marginEnd="20dp"
                app:cardCornerRadius="10dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent">

                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <ImageView
                        android:id="@+id/iv_offer_details_image"
                        android:layout_width="0dp"
                        android:layout_height="335dp"
                        android:background="@drawable/food_item_temp"
                        android:scaleType="centerCrop"
                        android:src="@drawable/bg_transparent_gradient"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="parent"
                        app:layout_constraintTop_toTopOf="parent" />

                    <TextView
                        android:id="@+id/tv_offer_details_name"
                        style="@style/colorBlackTextStyle.size20"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_marginStart="12dp"
                        android:layout_marginTop="10dp"
                        android:fontFamily="@font/myraid_pro_bold"
                        android:text="Offer Name Here"
                        app:layout_constraintStart_toStartOf="@id/iv_offer_details_image"
                        app:layout_constraintTop_toTopOf="@id/iv_offer_details_image" />


                </androidx.constraintlayout.widget.ConstraintLayout>
            </androidx.cardview.widget.CardView>

            <TextView
                android:id="@+id/tv_offer_details_ends"
                style="@style/colorLightGrayTextStyle.size18"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="20dp"
                android:layout_marginTop="15dp"
                android:fontFamily="@font/myraid_pro_semibold"
                android:text="@string/text_offer_ends"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/cardView_offer_details" />

            <TextView
                android:id="@+id/tv_offer_details_end_countdown"
                style="@style/colorBlackTextStyle.size20"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="5dp"
                android:fontFamily="@font/myraid_pro_semibold"
                android:gravity="start"
                android:text="2 Days 10 Hours"
                app:layout_constraintBottom_toBottomOf="@+id/tv_offer_details_ends"
                app:layout_constraintStart_toEndOf="@+id/tv_offer_details_ends" />

            <TextView
                android:id="@+id/label_offer_details_terms"
                style="@style/colorBlackTextStyle.size16"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="20dp"
                android:layout_marginTop="16dp"
                android:fontFamily="@font/myraid_pro_regular"
                android:gravity="start"
                android:text="@string/label_terms"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_offer_details_ends" />

            <TextView
                android:id="@+id/tv_offer_details_terms"
                style="@style/colorBlackTextStyle.size16"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="20dp"
                android:layout_marginTop="4dp"
                android:layout_marginEnd="20dp"
                android:fontFamily="@font/myraid_pro_regular"
                android:gravity="start"
                android:text="@string/description_offer_terms"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/label_offer_details_terms" />


            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/layout"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginTop="88dp"
                android:background="@color/colorRed"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_offer_details_terms">

                <Button
                    android:id="@+id/btn_redeem_at_cashier"
                    style="@style/PrimaryButtonStyle.padding4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="15dp"
                    android:fontFamily="@font/myraid_pro_bold"
                    android:text="@string/action_redeem_at_cashier"
                    app:layout_constraintBottom_toTopOf="@+id/btn_redeem_and_order"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintVertical_chainStyle="packed" />

                <Button
                    android:id="@+id/btn_redeem_and_order"
                    style="@style/PrimaryButtonStyle.padding4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="16dp"
                    android:layout_marginBottom="16dp"
                    android:fontFamily="@font/myraid_pro_bold"
                    android:text="@string/action_redeem_and_order"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/btn_redeem_at_cashier" />

            </androidx.constraintlayout.widget.ConstraintLayout>

        </androidx.constraintlayout.widget.ConstraintLayout>

    </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
<ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar_offer_details"
        android:fillViewport="true">

也许在 ScrollView 上设置 android:fillViewport="true" 可以解决您的问题:

你没有提到的是它现在在做什么。你说你想要做点什么,但我有点不清楚。

你指的是 android:id="@+id/layout" 吗?

如果是这样的话,那我觉得你问的太过分了。

您的层次结构如下所示:

<CL> (ConstraintLayout)
   <Toolbar>
   <ScrollView>
      <CL>
        <CardView>
           <CL>
             <ImageView />
             <TextView />
           </CL>
        </CardView>
        <TextView />
        <TextView />
        <TextView />
        <TextView />
        <CL>
           <Button>
           <Button>
        </CL>
     </CL>
   </ScrollView>
</CL>

我最初的建议是在你使用任何 hack 之前(你不应该喜欢 android:fillViewport)评估你的约束是否满足所有可能的方向和大小。

ScrollView 需要执行大量计算(它必须询问其子项的大小)。有些事情他们不可能按照写的去做,因为有些是 "wrap" 的内容,但没有完全的限制,这意味着他们必须等待和衡量自己才能告诉 "I need this amount of space"。现在将所有这些都放在 measure/layout 通道中,想象一下这需要多长时间以及对引擎来说有多痛苦。

滚动视图也不是最好的,因为滚动视图必须测量所有内容才能绘制其可滚动部分(滚动条和内容)。

我认为这里缺少的部分可能是垂直链,但请记住:

当您要求小部件对其内容进行 WRAP 并且您只提供一个约束时,例如设置为 WRAP 其高度的 TextView,但只有 "top_to_" 约束(但没有 bottom_to...) 然后小部件没有已知的大小,也没有计算它的方法,直到它的文本被测量(一个昂贵且缓慢的操作),因为你可以有任意的字体大小,填充等。一个 TextView是一个简单的例子,ImagesViews 是另一个类似的例子,因为图像源现在可能在编译时和运行时都是已知的。

避免大多数这些问题的方法是正确 chain 小部件并在需要时让它们包装其内容。

有一个 app:layout_constraintHeight_default="wrap" 属性 您可以用来让小部件知道它可以在需要时打破约束。

我建议您多尝试一下,因为声明约束的方式还有改进的余地。