同时在两个view中约束TextView

Constrain TextView in two views at the same time

我必须构建这样的布局:

有两个 TextView,蓝色和黑色。

“黑色”TextView 内的字符串应放在“蓝色”TextView 之后,如果文本太长,则向下跳转,就像它也被限制在图像右侧一样。 我不能使用 SpannableString 之类的东西,因为“蓝色”TextView 在某些情况下可能是 ImageView

我正在尝试使用 ConstraintLayout,我认为这是我们拥有的最完整的布局,但我无法弄清楚。

如果有人能展示一些组件、方法或解决方法来解决这个问题,我将不胜感激。 谢谢!

----- 已编辑 ---- 另一个例子:

你好尝试 Google's FlexboxLayout 将 flexWrap 属性设置为 wrap

最简单的解决方案是使用跨度将黑色文本放置在蓝色文本的 TextView 中。如果黑色文本在 ImageView 内,则将黑色文本 ImageView 约束到最左边的 ImageView。当你有不在 ImageView 中的黑色文本时,使 ImageView 的 可见性等于“消失”。

但我们假设您有两个 TextView,其中的文本无法合并。

案例 1 - 两个 TextViews

除了最左边的ImageView,还有两个TextView。一个拿着蓝色文本,一个拿着黑色文本。目标是让这两个 TextView 看起来像是单个 TextView 的一部分,这样黑色文本紧跟在蓝色文本之后。

为此,将黑色 TextView 放置在完全覆盖蓝色 TextView 的位置。这可以通过 ConstraintLayout.

轻松实现

activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginStart="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/dandelion_flower" />

    <TextView
        android:id="@+id/textBlue"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:text="Blue text that spane more than one line of its TextView."
        android:textColor="@android:color/holo_blue_bright"
        app:layout_constrainedWidth="true"
        app:layout_constraintBottom_toBottomOf="@id/imageView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/imageView"
        app:layout_constraintTop_toTopOf="@+id/imageView" />

    <TextView
        android:id="@+id/textBlack"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:text="This is some black text"
        android:textColor="@android:color/black"
        app:layout_constrainedWidth="true"
        app:layout_constraintBottom_toBottomOf="@+id/imageView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/imageView"
        app:layout_constraintTop_toTopOf="@+id/imageView" />

</androidx.constraintlayout.widget.ConstraintLayout>

如果不进行调整,黑色文字只会出现在蓝色文字之上。现在的目标是填充蓝色文本 TextView 足够 space 以便它移动到蓝色文本的末尾。我们可以通过使用换行符(将其向下移动)和 space 字符(将其移动到上方)来调整黑色文本来做到这一点。执行此操作的一个地方是在 onCreate() 函数中。 (请参阅以下代码中的注释。)

// Wait for the layout to complete before getting measurements.
findViewById<TextView>(R.id.textBlue).doOnNextLayout {
    val blueText = it as TextView
    val blackText = findViewById<TextView>(R.id.textBlack)
    // The TextViews have been laid out. Determine how many lines are used for the blue text.
    val blueLayout = blueText.layout
    val blueLineCount = blueText.layout.lineCount
    // And the width in pixels of the last line.
    val lastLineWidth = blueLayout.getLineWidth(blueLineCount - 1)
    // We will skip over the full lines with newline characters and pad out the last line
    // with spaces.
    val newLines = "\n".repeat(blueLineCount - 1)
    val spaceWidth = blackText.paint.measureText(" ")
    val padChars = " ".repeat((lastLineWidth / spaceWidth).toInt() + 1)
    blackText.text = "$newLines$padChars${blackText.text}"
}

结果如下:

您可能需要对视图进行一些调整才能使其正常工作,但这是总体思路。

案例 2 - 一个 TextView 和一个带有 Text

ImageView

在这种情况下,带有文本的 ImageView 被限制到另一个 ImageView 并位于 TextView。如何实现取决于您的要求。

一种布局可用于两种情况。在案例 #1 中,第二个 ImageView 会将其可见性设置为“消失”或“不可见”。在案例 #2 中,黑色文本 TextView 的可见性将设置为“消失”或“不可见”。

我最初认为 LeadingMarginSpan 是可行的方法,但如果黑色文本应该从第一行以外的任何行开始,就会遇到困难。


如果您想围绕 ImageView this Stack Overflow 问题和答案流动文字。