如何使用 ConstraintLayout 制作视图 "wrap_content but not larger than"?

How to make view "wrap_content but not larger than" with ConstraintLayout?

我连续有 3 个视图:标题、版本和图像视图(用作按钮):

  1. 标题应该是 wrap_content 但要遵守以下规则
  2. 版本应为 wrap_content,在标题右侧和图像视图左侧
  3. imageview 有固定的大小并且在 parent
  4. 的右上角

问题是如果标题太大,版本会移到右边并且不遵守规则 "version is to the left of imageview":

所以我需要限制标题宽度并使版本可见且不向右移动。

这里是XML:

<?xml version="1.0" encoding="utf-8"?>
<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:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:background="#b3b2b2">

    <!--  -->
    <TextView
        android:id="@+id/LibraryWithVersionItem.title"
        android:layout_width="0dp"
        android:textStyle="bold"
        android:textSize="@dimen/fontSize18"
        android:textColor="@color/mySecondaryDarkColor"
        android:layout_height="wrap_content"
        android:ellipsize="middle"
        tools:text="ExampleLibrary 01234567890123456789012345"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="8dp"
        android:layout_marginLeft="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        />

    <Spinner
        android:id="@+id/LibraryWithVersionItem.versions"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:textSize="@dimen/fontSize16"
        android:textColor="@color/mySecondaryDarkColor"
        tools:listitem="@layout/library_version"
        android:layout_marginTop="@dimen/margin8"
        android:layout_marginLeft="@dimen/margin8"
        android:layout_marginRight="@dimen/margin8"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/LibraryWithVersionItem.title"
        app:layout_constraintRight_toLeftOf="@+id/LibraryWithVersionItem.info"
        app:layout_constraintHorizontal_bias="0.0"/>

    <TextView
        android:id="@+id/LibraryWithVersionItem.sentence"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/LibraryWithVersionItem.title"
        tools:text="Some library description in one sentence\nbut two lines"
        android:layout_marginTop="@dimen/margin8"
        android:layout_marginLeft="@dimen/margin8"
        app:layout_constraintRight_toLeftOf="@+id/LibraryWithVersionItem.install"
        android:layout_marginRight="8dp"
        app:layout_constraintHorizontal_bias="0.0"/>

    <TextView
        android:id="@+id/LibraryWithVersionItem.isInstalled"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/LibraryManager.installed"
        android:textColor="#1a7c1a"
        android:layout_marginTop="@dimen/margin8"
        android:layout_marginBottom="@dimen/margin8"
        android:layout_marginLeft="@dimen/margin8"
        android:layout_marginRight="@dimen/margin8"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/LibraryWithVersionItem.sentence"
        app:layout_constraintRight_toLeftOf="@+id/LibraryWithVersionItem.install"
        app:layout_constraintHorizontal_bias="0.0"/>

    <!-- information button -->
    <ImageView
        android:id="@+id/LibraryWithVersionItem.info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/margin8"
        android:paddingLeft="@dimen/margin8"
        android:paddingRight="@dimen/margin8"
        android:paddingBottom="@dimen/margin8"
        android:scaleType="center"
        android:src="@drawable/ic_info_outline_white_24dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <!-- install button -->
    <ImageView
        android:id="@+id/LibraryWithVersionItem.install"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="@dimen/margin8"
        android:paddingRight="@dimen/margin8"
        android:paddingTop="@dimen/margin8"
        android:paddingBottom="@dimen/margin8"
        android:scaleType="center"
        android:src="@drawable/ic_get_app_white_24dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/LibraryWithVersionItem.info"/>


</android.support.constraint.ConstraintLayout>

PS 1. layout_width="0dp" + app:layout_constraintWidth_default="wrap" 似乎正是我所需要的 ("wrap_content but not breaking the constraints") 但它不起作用(仍然比要求的大):

<TextView
        android:id="@+id/LibraryWithVersionItem.title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:ellipsize="middle"
        android:textColor="@color/mySecondaryDarkColor"
        android:textSize="@dimen/fontSize18"
        android:textStyle="bold"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_default="wrap"
        tools:text="ExampleLibrary 01234567890123456789012345"

PS 2. 为版本设置最小约束宽度 (app:layout_constraintWidth_min="60dp") 也无济于事 - 它不可见,因为它移动得太右了。

在 ConstraintLayout 中,您可以添加一个或多个水平或垂直的辅助线,这有助于将屏幕分成几部分。 我通常使用 *_pct 属性添加指南,该属性将位置设置为屏幕的百分比 width/height。

标题和版本应该在链中并且 app:layout_constraintWidth_default="wrap" 使用:

<?xml version="1.0" encoding="utf-8"?>
<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:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:background="#b3b2b2">

    <!-- information button -->
    <ImageView
        android:id="@+id/LibraryWithVersionItem.info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/margin8"
        android:paddingLeft="@dimen/margin8"
        android:paddingRight="@dimen/margin8"
        android:paddingBottom="@dimen/margin8"
        android:scaleType="center"
        android:src="@drawable/ic_info_outline_white_24dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <!--  -->
    <TextView
        android:id="@+id/LibraryWithVersionItem.title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:ellipsize="middle"
        android:textColor="@color/mySecondaryDarkColor"
        android:textSize="@dimen/fontSize18"
        android:textStyle="bold"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_default="wrap"
        tools:text="ExampleLibrary 01234567890123456789012345"
        app:layout_constraintRight_toLeftOf="@+id/LibraryWithVersionItem.versions"
        android:layout_marginRight="8dp"
        android:layout_marginLeft="8dp"
        android:paddingBottom="1dp"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintHorizontal_bias="0.0"/>

    <Spinner
        android:id="@+id/LibraryWithVersionItem.versions"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/fontSize16"
        android:textColor="@color/mySecondaryDarkColor"
        tools:listitem="@layout/library_version"
        app:layout_constraintRight_toLeftOf="@id/LibraryWithVersionItem.info"
        app:layout_constraintLeft_toRightOf="@+id/LibraryWithVersionItem.title"
        android:layout_marginRight="0dp"
        app:layout_constraintBottom_toBottomOf="@+id/LibraryWithVersionItem.title"
        android:layout_marginBottom="0dp"/>

    <TextView
        android:id="@+id/LibraryWithVersionItem.sentence"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/LibraryWithVersionItem.title"
        tools:text="Some library description in one sentence\nbut two lines"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="@dimen/margin8"
        app:layout_constraintRight_toLeftOf="@+id/LibraryWithVersionItem.install"
        android:layout_marginRight="8dp"
        app:layout_constraintHorizontal_bias="0.0"
        android:layout_marginStart="@dimen/margin8"
        android:layout_marginEnd="8dp"/>

    <TextView
        android:id="@+id/LibraryWithVersionItem.isInstalled"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/LibraryManager.installed"
        android:textColor="#1a7c1a"
        android:layout_marginTop="@dimen/margin8"
        android:layout_marginLeft="@dimen/margin8"
        android:layout_marginRight="@dimen/margin8"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/LibraryWithVersionItem.sentence"
        app:layout_constraintRight_toLeftOf="@+id/LibraryWithVersionItem.install"
        app:layout_constraintHorizontal_bias="0.0"
        android:layout_marginStart="@dimen/margin8"
        android:layout_marginEnd="@dimen/margin8"/>

    <!-- install button -->
    <ImageView
        android:id="@+id/LibraryWithVersionItem.install"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="@dimen/margin8"
        android:paddingRight="@dimen/margin8"
        android:paddingTop="@dimen/margin8"
        android:paddingBottom="@dimen/margin8"
        android:scaleType="center"
        android:src="@drawable/ic_get_app_white_24dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/LibraryWithVersionItem.info"/>

</android.support.constraint.ConstraintLayout>

我已尝试将版本与标题基线对齐,但如果标题是 2 行或更多行,它会与第一行对齐,这是不需要的。所以我不得不将版本对齐到标题底部和硬编码标题 -3 底部填充。

但是,它在 Android Studio 中看起来很理想:

但在硬件设备上看起来不同:

Layout Inspector 中分析时,我可以看到标题宽度计算错误:

可能是在 RecyclerView 中使用它的副作用,但无论如何...

您要设置android:layout_width="0dp"

使用wrap_content,视图会随着内容无限增长。通过使用 0dp 并设置其约束,视图将具有默认的最大尺寸,并且内容将在其中增长到极限。


使用 android:layout_width="wrap_content"


使用 android:layout_width="0dp"


从现在开始,发挥你的魔力。可以设置TextView的android:maxLines="1"android:ellipsize="end",达到最大尺寸时加三个点。

最终布局xml

<?xml version="1.0" encoding="utf-8"?>
<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">

    <TextView
        android:id="@+id/item_a_receber_historico"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:maxLines="1"
        android:ellipsize="end"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="John Dreadpool Lennon Of House Stark Man This Name Is Huge!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/item_a_receber_valor"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <TextView
        android:id="@+id/item_a_receber_valor"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginTop="8dp"
        android:text="R0,00"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

我通过将 layout_width 设置为 wrap_content 并将 maxWidth 设置为一个值

来实现此目的