Android:如何在将包含在父布局中的布局中使用constraint_height_percent

问题描述

目前,我正在尝试使我的视图的高度和宽度相对于可用空间,因此我的 ui 将更加负责。我遇到的问题是,每当我尝试在父布局中包含此布局(例如,在 fragment_shop 中包含 shop_content)时,我包含的布局的高度和宽度不再起作用。

我做了一个小例子来说明这一点。在此示例中,您可以看到工具栏的高度应为给定高度的 17%。当我在子布局中查看我的设计选项卡时,一切正常,但是在我的 fragment_shopping_cart 中导入此布局时,视图仍然不可见/高度未正确显示

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"> <!-- Changing this to wrap_content makes weird stuff -->

    <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" <!-- Height should take 0.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>

它应该是什么样子

enter image description here

外观

enter image description here

在这里做错了什么?我感谢每一个帮助。注意:我是 Android 响应式 ui 的新手

编辑

由于这个问题越来越难理解,我将尝试用这个例子更好地解释它:我有一个名为 app_standard_checkout_btn 的布局,我在我的几个布局(包括它)中使用了它。此布局包含不同的视图,例如 工具栏(用作背景)、文本视图和其他内容

目前,工具栏的高度固定为 124dp,这就是问题所在。我不希望高度为 124dp,而是希望包含布局的整个可用高度的 0.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" <!-- THIS FIXED VALUE IS BAD -->
            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>

解决方法

这一行

app:layout_constraintHeight_percent="0.17"

属于 parent_layout,应该为 <include 标签设置或至少为 ConstraintLayout 放置在 child_layout(文件中的根视图)

,

您需要将 child_layout 的顶部约束到 ReyclerView 的底部

因此向 child_layout 中添加 bleow 约束

app:layout_constraintTop_toBottomOf="@+id/rv_shopping_cart"

此更改后,整个父布局将:

<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_constraintTop_toBottomOf="@+id/rv_shopping_cart"
            app:layout_constraintStart_toStartOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

编辑

我不希望高度为 124dp,而是希望包含布局的整个可用高度的 0.15

现在您希望 Toolbar 成为父布局的 17%,而它不是它的直接子级。这看起来很奇怪并且与 ConstraintLayout 指导不匹配因为工具栏不是父级 ConstraintLayout

的直接子级

因此,您不能将 Toolbar 约束到父 ConstraintLayout;相反,您可以将整个子布局约束到父布局。因此,您需要通过硬编码或约束来限制整个子布局的高度。在不限制高度的情况下,您的共享图片中的布局会消失。

在最佳答案中,我将其约束在 RecyclerView 的底部,这就是您在与 RecyclerView 共享的 app:layout_constraintBottom_toTopOf="@id/shopping_cart_btn" 约束中所做的。这可能并不完美,因为我们无法在编译时预测 RecyclerView 的高度。

因此,这是使用 app:layout_constraintHeight_percent 约束来约束子布局相对于父布局的高度的另一种选择,就像您对其 Toolbar 所做的一样,但百分比大于 17% .由你来选择一个合适的百分比,这里我会选择 50%。

现在父级的高度是 100%。孩子的高度是 50%,因为您需要 Toolbar 的高度是父母的 17%,那么现在将它加倍到 34%。你必须根据你选择的整个子布局的值来改变它。

现在父布局将是

父布局:

<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_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_constraintHeight_percent="0.5"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

子布局:

<?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"
    android:layout_width="match_parent"
    android:layout_height="0dp"> <!-- Changing this to wrap_content makes weird stuff -->

    <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_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_percent="0.34"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>