在ConstraintLayout中,wrap_content的视图会伸展到屏幕外部

194

我正在尝试使用ConstraintLayout实现一个简单的聊天气泡。这是我想要实现的效果:

enter image description here enter image description here

然而,wrap_content并不能达到我想要的效果。它会遵循边距,但会超出视图边界。以下是我的布局:

<?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/chat_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintHorizontal_bias="0"
        tools:background="@drawable/chat_message_bubble"
        tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sodales accumsan tortor at bibendum."
        android:layout_marginStart="64dp"
        android:layout_marginLeft="64dp"
        android:layout_marginEnd="32dp"
        android:layout_marginRight="32dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp" />
</android.support.constraint.ConstraintLayout>

这将呈现如下:

输入图像描述

我正在使用com.android.support.constraint:constraint-layout:1.0.0-beta4

我做错了什么吗?这是一个错误还是只是一个不直观的行为?我能否使用ConstraintLayout实现适当的行为(我知道我可以使用其他布局,但我特别询问ConstraintLayout)。


顺便说一下,在你的情况下,我猜水平偏差是罪魁祸首。尝试移除layoutright to right of和bias。 - Mohammed Atif
1
水平偏移是必要的,否则气泡会居中。没有从右到左的布局,右边距不会被考虑进去,这不是我们想要的结果。我尝试按照您的建议删除它们,但是没有帮助。 - Marcin Jedynak
1
问题肯定是水平偏差为0。我会尽快检查可能的解决方案,并发布它,因为我也在使用约束布局处理类似的问题。 - Mohammed Atif
1
@nmu聊天气泡来自tools:background="@drawable/chat_message_bubble"。要实现它,您必须在drawable文件夹中创建chat_message_bubble.xml文件,然后添加以下代码: <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#FB4382"/> <corners android:radius="10dip"/> </shape> - Eugene Brusov
对我来说,这在链接视图上不起作用。因此,一个视图具有包裹内容,然后获取整个链屏幕的所有空间。 :( - Mahdi
显示剩余2条评论
7个回答

444

更新内容(ConstraintLayout 1.1.+)

使用 app:layout_constrainedWidth="true"android:layout_width="wrap_content"

之前的方法(已废弃):

app:layout_constraintWidth_default="wrap"android:layout_width="0dp"


10
是的,我相信自从ConstraintLayout 1.1.0 beta 2版本以后就是这样了。https://androidstudio.googleblog.com/2017/10/constraintlayout-110-beta-2.html - Fifer Sheep
4
这是1.1版本的最新内容:https://medium.com/google-developers/introducing-constraint-layout-1-1-d07fc02406bc - Esdras Lopez
4
喜欢StackOverflow!谢谢,这对我很有帮助!保持包装内容,但不要超出限制!#TIL - Dennis Anderson
3
好的,我会尽力进行翻译:真是个好答案,我不知道这个东西的存在!谢谢,经过两个小时的试错,这个方法非常有效! - dev2505
3
你让我今天过得很愉快。 - Alex

300

已过时: 查看更好的答案

目前(1.0 beta 4)使用ConstraintLayout无法实现您想要的效果:

  • wrap_content 只会要求小部件自行测量其大小,但不会限制它根据约束条件的扩展
  • match_constraints(0dp)根据约束条件限制小部件的大小......但即使wrap_content可以更小(第一个示例),它也会与之相匹配,这也不是您想要的。

所以,目前对于这个特定情况,您运气不佳 :-/

现在......我们正在考虑为match_constraints添加额外的功能,以处理这种具体情况(如果大小超过约束条件,表现为wrap_content)。

我无法保证这个新功能在1.0版本发布之前就能推出。

编辑: 我们在1.0版本中添加了此功能,即使用属性app:layout_constraintWidth_default="wrap"(宽度设置为0dp)。如果设置了此属性,则小部件的大小将与使用wrap_content相同,但将受到约束的限制(即不会超出约束条件)

更新 现在这些标签已经过时,改为使用layout_width="WRAP_CONTENT"和layout_constrainedWidth="true"。


1
这对我来说是一个非常棘手的问题。目前我无法在TextView中使用复合绘图,因为如果我将其设置为“match_constraints”,即使文本非常短,复合绘图也会位于最右侧。 - Paul Woitaschek
2
@NicolasRoard:你能帮我解决一下约束布局的问题吗?我在上半部分有一张图片,使用了0.4的参考线,下面是一些内容。但是当我将约束布局设置为wrap_content时,它只占据了屏幕的0.4(下面一半的文本视图也无法显示)。我已经使用了app:layout_constraintWidth_default="wrap"和库的v1.0.2版本,但没有起到作用。 - Rat-a-tat-a-tat Ratatouille
4
"app:layout_constraintWidth_default="wrap",将宽度设置为0dp会很好地实现此效果!" - Tunji_D
14
文档/说明中应该明确表达这一点。 - SQLiteNoob
7
编辑功能是否应该拥有更高的突出度?它在原始内容下很容易被忽略。感谢您的回答。谢谢@NicolasRoard。 - Tom Howard
显示剩余11条评论

38

正如Nikolas Roard所提到的,您应该添加app:layout_constraintWidth_default="wrap"并将宽度设置为0dp。要将气泡右对齐,您应将 layout_constraintHorizontal_bias设为1.0。

以下是最终源代码:

<android.support.constraint.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" >

    <TextView
        android:id="@+id/chat_message"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:layout_marginTop="8dp"
        android:layout_marginStart="64dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintWidth_default="wrap"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:background="@drawable/chat_message_bubble"
        android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sodales accumsan tortor at bibendum." />

</android.support.constraint.ConstraintLayout>

结果看起来像这样:

在此输入图片描述


我认为这是因为 OP 想要在左侧有一个小气泡,而你的在右侧,这改变了需求。 - Waza_Be
2
重要部分在于 app:layout_constraintHorizontal_bias="1.0" - Lester
1
是的,如果你想要使用开始而不是结束对齐,请使用app:layout_constraintHorizontal_bias="0"(注意:浮点数不是必需的) - Kenny

13

如其他回答所述,从ConstraintLayout 1.0开始就可以实现这一点,但在最新版本(1.1.x)中,它们已更改了操作方式。

自ConstraintLayout 1.1发布以来,旧的app:layout_constraintWidth_default="wrap"app:layout_constraintHeight_default="wrap"属性已经过时

如果想要提供wrap_content的行为,但仍然强制对视图进行约束,则应将其宽度和/或高度设置为wrap_content结合使用app:layout_constrainedWidth=”true|false”和/或app:layout_constrainedHeight=”true|false”属性,如文档所述:

WRAP_CONTENT:强制约束(从1.1版开始)如果将维度设置为WRAP_CONTENT,则在1.1版之前,它们将被视为字面维度——也就是说,约束不会限制结果维度。虽然通常这已经足够了(并且更快),但在某些情况下,您可能想使用WRAP_CONTENT,但仍然要强制执行约束以限制结果维度。在这种情况下,您可以添加相应的属性之一:

app:layout_constrainedWidth=”true|false” app:layout_constrainedHeight=”true|false”

关于最新版本,在我回答这个问题的时候,ConstraintLayout 已经更新到版本 1.1.2


6

app:layout_constraintWidth_default属性及其替代方案的弃用

@nicolas-roard提供的app:layout_constraintWidth_default="wrap"android:layout_width="0dp"现在已经被弃用

请使用app:layout_constrainedWidth="true"android:layout_width="wrap_content"

我不知道为什么废除它,但这确实出现在ConstraintLayout的源代码中。


-8
我使用这个。
app:layout_constraintEnd_toEndOf="parent"

这如何回答原帖的问题?这如何包装内容? - Alex

-8

你应该进行替换

android:layout_width="wrap_content"

使用

android:layout_width="match_parent"

从您的TextView中获取文本,然后相应地调整填充和边距。 我已经更新了您的代码。
<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/chat_message"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    android:layout_marginEnd="10dp"
    android:layout_marginLeft="60dp"
    android:layout_marginRight="10dp"
    android:layout_marginStart="60dp"
    android:layout_marginTop="8dp"
    android:padding="16dp"
    app:layout_constraintTop_toTopOf="parent"
    tools:background="#c9c7c7"
    tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris sodales accumsan tortor at bibendum." />

你将会得到如下结果 输入图像描述


在 ConstraintLayout 中,您应避免为任何视图使用 "match_parent"。请查看此处的 "注意事项":https://developer.android.com/training/constraint-layout/index.html#adjust-the-view-size - Eugene Brusov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接