【问题标题】:Constrain TextView in two views at the same time同时在两个视图中约束 TextView
【发布时间】:2020-11-02 20:33:37
【问题描述】:

我必须构建这样的布局:

TextView 有两个,一个是蓝色的,一个是黑色的。

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

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

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

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

【问题讨论】:

  • 你能详细解释一下为什么 SpannableString 没用吗?
  • 不能只有一个 TextView,因为“蓝色”在某些情况下可以是 ImageView,因此“黑色”TextView 的行为应该与第一个 View is anchored 无关。谢谢!

标签: android android-layout textview android-constraintlayout


【解决方案1】:

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

但是让我们假设您有两个 TextViews,其中包含无法组合的文本。

案例 1 - 两个 TextViews

除了最左边的ImageView,还有两个TextView。一个持有蓝色文本,一个持有黑色文本。目标是让这两个 TextViews 看起来像是单个 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 将有足够的空间,以便它移动到蓝色文本的末尾。我们可以通过使用换行符(将其向下移动)和空格字符(将其向上移动)调整黑色文本来做到这一点。在onCreate() 函数中可以做到这一点。 (参见下面代码中的 cmets。)

// 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 和一个带有文本的 ImageView

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

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

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


如果您想在 ImageView 周围排列文本,this Stack Overflow 问题和答案应该会有所帮助。

【讨论】:

  • 非常感谢您的回复!案例#1 是真正的原创,并且按预期工作!问题出现在案例 #2 中,当您已经注意到将 TextView 锚定到左侧一个视图并不容易(甚至不可能)并且如果文本在该视图下方跳得太远......你看到我的第二个截图了吗我的问题?你可以更好地看到我需要什么。谢谢!
  • @Ricard 我有黑色文本可能是 ImageView 而不是你所说的蓝色..我会纠正那个。我不清楚第二个例子代表什么。哪一部分是TextView,哪一部分是ImageView?如果您希望 ImageView 的文本像 TextView 中的文本一样流动,那么我相信您不走运。
  • 对不起,如果我解释不好。在我发布的第二张图片中,“逗号”是一个 ImageView,文本是一个 TextView,TextView 内的文本从 ImageView 的末尾开始,如果可以不覆盖 ImageView(逗号),则在下面。
  • @Ricard 让我们看看我是否理解:照片是一个 ImageView,逗号是另一个单独的 ImageView。名称是一个 TextView,其余文本是另一个 TextView。对吗?
  • @Ricard 查看答案的最后一行。我认为这是可以提供帮助的。您还需要根据可见性属性是否正在使用第二个 ImageView 来调整视图。
【解决方案2】:

您好,试试 Google's FlexboxLayout,将 flexWrap 属性设置为 wrap

【讨论】:

  • 感谢您的选择,但成功了一半。我一直在玩FlexBoxLayout,但我只实现了让“黑色”TextView 完全跳到下面,但不像我发布的图像。我需要第二行跳到下面而不是整个TextView
  • 我在我的问题中添加了另一个我需要实现的示例!
猜你喜欢
  • 1970-01-01
  • 2014-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多