Android:被父布局include的子布局中如何正确使用layout_constraintHeight_percent
Android 响应式布局适配遇 include 后百分比尺寸失效问题
我目前在做响应式UI,尝试让控件宽高相对于容器可用空间动态适配,以此提升UI的适配性,过程中遇到一个问题:只要是带百分比尺寸设置的子布局,通过include标签引入父布局后(比如把shop_content引入fragment_shop布局),子布局的宽高设置就会失效。
我写了最小复现案例来定位问题:我希望页面内的toolbar高度占容器可用总高度的17%,单独打开子布局的设计预览页时所有表现正常,但把这个布局引入购物车页面对应的父布局后,该控件要么完全不可见,要么高度显示异常。
子布局(child_layout)
<androidx.constraintlayout.widget.ConstraintLayout 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"> <!-- 根布局如果改为wrap_content,异常表现会更明显 --> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/calibrate_btn_background" android:layout_width="match_parent" android:layout_height="0dp" android:background="@color/color_primary" android:clickable="false" app:layout_constraintHeight_percent="0.17" <!-- 高度设置为占父容器的17% --> app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
父布局(parent_layout)
<layout 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"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".framework.ui.view.fragments.shop.ShoppingCartFragment"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/shopping_cart_toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/color_primary" app:title="@string/bottom_nav_shopping_cart" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> </com.google.android.material.appbar.MaterialToolbar> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rv_shopping_cart" android:layout_width="match_parent" android:layout_height="0dp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_constraintBottom_toTopOf="@id/shopping_cart_btn" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/shopping_cart_toolbar" tools:listitem="@layout/shopping_cart_list_item" /> <include android:id="@+id/shopping_cart_btn" layout="@layout/child_layout" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
表现差异
- 预期效果:引入的子布局在父容器底部正常占位,内部toolbar占该区域17%高度,位置显示正常
- 实际效果:toolbar要么完全不可见,要么高度计算错误,显示异常
刚接触Android响应式UI开发,想请教是哪部分设置出了问题。
补充使用场景
为了更清晰说明问题,我再举另一个复用场景:
我有一个通用复用布局app_standard_checkout_btn,会在多个页面通过include方式引入,这个布局包含作为背景的toolbar、文本框等各类控件。
目前这个背景toolbar的高度是写死的124dp,这就是问题核心:我不希望用固定高度,而是希望这个toolbar在布局被引入后,高度占所属父容器可用总高度的15%(部分场景下这个15%计算出的高度刚好等于124dp),想请教这种效果要如何实现。
对应的复用布局代码如下:
<?xml version="1.0" encoding="utf-8"?> <layout 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"> <data> <variable name="price" type="Float" /> <variable name="btnText" type="String" /> <variable name="btnIcon" type="android.graphics.drawable.Drawable" /> <variable name="btnTextCapitalized" type="Boolean" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/calibrate_btn_background" android:layout_width="match_parent" android:layout_height="124dp" <!-- 这个固定高度值不合理 --> android:background="@color/color_btn_gray" android:clickable="false" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> <com.google.android.material.textview.MaterialTextView android:id="@+id/calibrate_btn_tv_sum" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/standard8dpMargin" android:layout_marginEnd="@dimen/big16dpMargin" android:text="@string/calibrate_btn_price" android:textColor="@color/color_text_dark" android:textSize="@dimen/textHeadlineNormal2" app:layout_constraintEnd_toStartOf="@+id/shop_item_price" app:layout_constraintTop_toTopOf="@+id/calibrate_btn_background" /> <TextView android:id="@+id/shop_item_price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{price}" android:textColor="@color/color_text_blue" android:textSize="@dimen/textHeadlineNormal2" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="@+id/calibrate_btn_tv_sum" app:layout_constraintEnd_toStartOf="@+id/calibbrate_btn_tv_intern_curr" app:layout_constraintTop_toTopOf="@+id/calibrate_btn_tv_sum" tools:text="4800.00" /> <TextView android:id="@+id/calibbrate_btn_tv_intern_curr" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/currency" android:textColor="@color/color_text_blue" android:textSize="@dimen/textHeadlineNormal2" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="@+id/shop_item_price" app:layout_constraintEnd_toEndOf="@+id/calibrate_btn_next" app:layout_constraintTop_toTopOf="@+id/shop_item_price" /> <com.google.android.material.textview.MaterialTextView android:id="@+id/calibrate_btn_tv_description" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:text="@string/calibrate_btn_desc" android:textColor="@color/color_text_gray" android:textSize="@dimen/textDescriptionNormal4" app:layout_constraintEnd_toEndOf="@+id/calibrate_btn_next" app:layout_constraintTop_toBottomOf="@+id/shop_item_price" /> <com.google.android.material.button.MaterialButton android:id="@+id/calibrate_btn_next" android:layout_width="match_parent" android:layout_height="56dp" android:layout_marginStart="@dimen/big16dpMargin" android:layout_marginEnd="@dimen/big16dpMargin" android:layout_marginBottom="@dimen/standard8dpMargin" android:clickable="true" android:focusable="true" android:text="@{btnText}" android:textAllCaps="@{btnTextCapitalized}" android:textSize="@dimen/textDescriptionNormal1" android:textStyle="normal" app:backgroundTint="@color/color_btn_blue" app:icon="@{btnIcon}" app:iconGravity="textStart" app:layout_constraintBottom_toBottomOf="@id/calibrate_btn_background" app:layout_constraintEnd_toEndOf="@id/calibrate_btn_background" app:layout_constraintStart_toStartOf="@+id/calibrate_btn_background" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

