简体   繁体   English

同时在两个视图中约束 TextView

[英]Constrain TextView in two views at the same time

I have to build a layout like this:我必须构建这样的布局:

我正在尝试构建这样的布局

There are two TextView , the blue and the black one.有两个TextView ,蓝色和黑色一个。

String inside "black" TextView should be placed after "blue" TextView and if the text is too long jump down like if it was constrained also to the right of the image. “黑色” TextView字符串应放在“蓝色” TextView ,如果文本太长,则向下跳,就像它也被限制在图像右侧一样。 I can't use SpannableString and stuff because the "blue" TextView may be an ImageView in some cases.我不能使用SpannableString东西,因为在某些情况下,“蓝色” TextView可能是ImageView

I'm trying to use ConstraintLayout which I think is the most completed layout we have, but I can not figure it out.我正在尝试使用ConstraintLayout ,我认为这是我们拥有的最完整的布局,但我无法弄清楚。

I will appreciate if someone can show some component, approach or workaround to solve this.如果有人可以展示一些组件、方法或解决方法来解决这个问题,我将不胜感激。 Thanks!谢谢!

----- EDITED ---- Another example: ----- 编辑 ---- 另一个例子:

在此处输入图片说明

The easiest solution would be to use a span to place the black text within the TextView of the blue text.最简单的解决方案是使用跨度将黑色文本放置在蓝色文本的TextView中。 If the black text is within an ImageView then constrain the black text ImageView to the leftmost ImageView .如果黑色文本在ImageView内,则将黑色文本ImageView限制在最左边的ImageView When you have black text which is not in an ImageView , make the ImageView's visibility equal to "gone".当您有不在ImageView中的黑色文本时,使ImageView 的可见性等于“消失”。

But let's assume that you have two TextViews with text that cannot be combined.但是让我们假设您有两个TextView,其中的文本无法组合。

Case 1 - Two TextViews案例 1 - 两个TextView

In addition to the leftmost ImageView , there are two TextViews .除了最左边的ImageView 之外,还有两个TextViews One holds blue text and one holds black text.一个包含蓝色文本,一个包含黑色文本。 The goal is to make these two TextViews appear like they are part of a single TextView such that the black text immediately follows the blue text.目标是使这两个TextView看起来像是单个TextView 的一部分,以便黑色文本紧跟在蓝色文本之后。

To do this, position the black TextView to completely overlay the blue TextView .为此,将黑色TextView定位为完全覆盖蓝色TextView This can be easily accomplished with a ConstraintLayout .这可以通过ConstraintLayout轻松完成。

activity_main.xml活动_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>

Without adjustment, the black text will just appear on top of the blue text.如果不进行调整,黑色文本只会出现在蓝色文本的顶部。 The goal now is to pad out the blue text TextView will enough space so that it moves to the end of the blue text.现在的目标是填充蓝色文本TextView将足够的空间,以便它移动到蓝色文本的末尾。 We can do this by adjusting the black text with newline characters (to move it down) and space characters (to move it over).我们可以通过用换行符(向下移动)和空格字符(将其移过)调整黑色文本来做到这一点。 One place to do this is in the onCreate() function.这样做的一个地方是在onCreate()函数中。 (See comments in the following code.) (请参阅以下代码中的注释。)

// 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}"
}

Here is the result:结果如下:

在此处输入图片说明

You may need to make some adjustments to the views to make this work, but this is the general idea.您可能需要对视图进行一些调整才能使其正常工作,但这是总体思路。

Case 2 - One TextView and an ImageView with Text案例 2 - 一个TextView和一个带文本的ImageView

In this case, the ImageView with text is constrained to the other ImageView and positioned below the TextView .在这种情况下,带有文本的ImageView被约束到另一个ImageView并位于TextView下方。 How this is accomplished depends on your requirements.如何实现取决于您的要求。

One layout can be used for both cases.一种布局可用于两种情况。 In case #1, the second ImageView would have its visibility set to "gone" or "invisible".在第 1 种情况下,第二个ImageView的可见性将设置为“消失”或“不可见”。 In case #2, the black text TextView would have its visibility set to "gone" or "invisible".在第 2 种情况下,黑色文本TextView的可见性将设置为“消失”或“不可见”。

I originally thought that a LeadingMarginSpan would be the way to go, but it runs into difficulties if the black text should start on any line but the first.我最初认为LeadingMarginSpan将是要走的路,但如果黑色文本应该从第一行以外的任何一行开始,就会遇到困难。


If you want to flow text around an ImageView this Stack Overflow question and answer(s) should help.如果你想在ImageView周围流动文本, 这个Stack Overflow 问题和答案应该会有所帮助。

嗨,尝试将 flexWrap 属性设置为 wrap 的Google 的 FlexboxLayout

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM