android - 多行 TextView 与其基线对齐(ConstraintLayout Android Studio)

标签 android alignment android-constraintlayout multiline

我有三个 TextViews "hi", "x""Hello World" 我想在底部对齐Hello World 文本(即 hi_x_World)。 Hello World 只有一行,但 layout_widthlayout_height 都设置为 wrap_content

它们有不同的字体大小,所以即使我可以很容易地对齐 TextView 框的底部,文本本身也不会对齐。

我发现了一个不同的 XML 参数 app:layout_constraintBaseline_toBaselineOf="@+id/text 当我在 TextView 中只有一行时它起作用。但是,当我有 2 行或更多行时(比如Hello World TextView)所考虑的基线在“Hello”而不是“World”中。

有什么方法可以更改设置以考虑“World”而不是“Hello”一词下方的基线?

enter image description here

最佳答案

第二次更新:这是查看从 Stack Overflow answer 中获取的第一个解决方案的另一种方式。这也适用于 ConstraintLayout。此解决方案使用自定义 TextView。自定义 TextViewgetBaseline() 函数返回 TextView 中最后一行文本的基线,而不是第一行的基线这是默认操作。这是一个不错的、干净的解决方案 (IMO),它考虑了多行 TextViews 以及重力等。

Kotlin 版本的 BaselineLastLineTextView

class BaselineLastLineTextView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : AppCompatTextView(context, attrs) {

    override fun getBaseline(): Int {
        val layout = layout ?: return super.getBaseline()
        val baselineOffset = super.getBaseline() - layout.getLineBaseline(0)
        return baselineOffset + layout.getLineBaseline(layout.lineCount - 1)
    }
}

第一次更新:这是对我下面的答案的更新,它仍然是一个有效的解决方案 (IMO)。这是一种不涉及任何 Java/Kotlin 代码的替代方法,仅使用 XML 即可完成。

创建一个不可见的 wrap_content TextView,其字体大小与“Hello World!”相同 TextView 。 (您可能还需要根据实际布局考虑填充和边距。)将这个新 View 限制在“Hello World!”的底部,使其不可见并将内容设置为较短的内容保证只占用一行。这将为您提供一个与“Hello World!”的最后一行具有相同基线的目标 View 。查看。

将“hi”和“x”的基线约束到新的invisible View 。所有 View 现在将共享相同的基线且无需编码。

enter image description here

<androidx.constraintlayout.widget.ConstraintLayout 
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/hiddenView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="A"
        android:textSize="50sp"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="@id/helloView"
        app:layout_constraintEnd_toEndOf="parent" />

    <TextView
        android:id="@+id/hiView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hi"
        android:textSize="46sp"
        app:layout_constraintBaseline_toBaselineOf="@id/hiddenView"
        app:layout_constraintEnd_toStartOf="@+id/xView"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/helloView" />

    <TextView
        android:id="@+id/xView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="x"
        android:textSize="36sp"
        app:layout_constraintBaseline_toBaselineOf="@id/hiddenView"
        app:layout_constraintEnd_toStartOf="@+id/helloView"
        app:layout_constraintStart_toEndOf="@+id/hiView"
        app:layout_constraintTop_toTopOf="@id/helloView" />

    <TextView
        android:id="@+id/helloView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello\nWorld!"
        android:textSize="50sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/xView"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:onClick="onClick"
        android:text="Adjust Base Lines"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/helloView" />


</androidx.constraintlayout.widget.ConstraintLayout>


第一个答案:如另一个答案所述,仅使用 ConstraintLayout 约束无法做到这一点。 您需要求助于程序化解决方案。

在每个 TextView 中都有一个 StaticLayout这可以揭示一些关于 typography 的信息的文字。引用静态布局,可以在适当的 View 中添加padding,使基线对齐。

在这个演示中,三个 TextViews 只是让它们的顶部对齐。最初, View 如下所示:

enter image description here

单击按钮时,将计算基线位置,并将填充添加到“hi”和“x”TextViews 的顶部。

enter image description here

细节会因实现而异,但这是通用技术。

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun onClick(view: View) {
        button.isEnabled = false
        // Get the StaticLayout from the TextView
        val layout = helloView.layout

        // Get the base line location for last line of Hello World! TextView, "hi" and "x"
        val helloBaseLIne = layout.getLineBaseline(layout.lineCount - 1)
        val hiBaseLine = hiView.layout.getLineBaseline(0)
        val xBaseLine = xView.layout.getLineBaseline(0)
        
        // Shift "hi" and "x" down so base lines match that of hello world!
        hiView.updatePadding(top = helloBaseLIne - hiBaseLine)
        xView.updatePadding(top = helloBaseLIne - xBaseLine)
    }
}

activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:id="@+id/layout"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/hiView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hi"
        android:textSize="46sp"
        app:layout_constraintTop_toTopOf="@id/helloView"
        app:layout_constraintEnd_toStartOf="@+id/xView"
        app:layout_constraintStart_toStartOf="parent"/>

    <TextView
        android:id="@+id/xView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="x"
        android:textSize="36sp"
        app:layout_constraintTop_toTopOf="@id/helloView"
        app:layout_constraintEnd_toStartOf="@+id/helloView"
        app:layout_constraintStart_toEndOf="@+id/hiView" />

    <TextView
        android:id="@+id/helloView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello\nWorld!"
        android:textSize="50sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/xView"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:text="Adjust Base Lines"
        android:onClick="onClick"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/helloView" />


</androidx.constraintlayout.widget.ConstraintLayout>

关于android - 多行 TextView 与其基线对齐(ConstraintLayout Android Studio),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57610578/

相关文章:

css - flexbox 中的 align-self 属性不起作用

android - 如何在android中使用java更改约束布局背景图像

android - 在constraintlayout中根据设备宽度设置 View 高度

android - 将 Intent 从广播接收器发送到android中正在运行的服务

html - CSS/HTML 左右浮动?

android - 位图/ Canvas : java. lang.IllegalArgumentException:宽度和高度必须 > 0

html - 文本溢出省略号

java - ConstraintLayout 不适用于某些值

android - 无法使用 fstream 和 ifstream 在 NDK C++ 中读取文件

Android:缩放 ImageView 及其 onDraw() 项目