如何在滚动视图中制作嵌套约束布局以匹配主父布局的大小
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 和更高的屏幕尺寸
我尝试只取出底部约束布局和两个按钮。它在一定程度上解决了问题但是它使小屏幕尺寸下的视图更难看
<?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"
属性 您可以用来让小部件知道它可以在需要时打破约束。
我建议您多尝试一下,因为声明约束的方式还有改进的余地。
编辑:我想要的是用两个按钮制作底部的红色部分,当屏幕尺寸大于 6.3 时,底部的整个 space 与顶部保持 88dp 的边距。 现在发生了什么:红色背景直到底部才占据 space(见屏幕截图)。我找不到使约束布局展开的方法 我想使 scrollView 内的底部约束布局与父布局大小相匹配,而不从底部创建任何间隙。这只发生在 6.3 和更高的屏幕尺寸
我尝试只取出底部约束布局和两个按钮。它在一定程度上解决了问题但是它使小屏幕尺寸下的视图更难看
<?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"
属性 您可以用来让小部件知道它可以在需要时打破约束。
我建议您多尝试一下,因为声明约束的方式还有改进的余地。