最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

android - How can I copy the line height config of one TextView to another TextView? - Stack Overflow

programmeradmin7浏览0评论

I am working on localizing my app into Bengal. I found that the Bengal numbers take up more line height than the arabic numbers do, and now I want to dynamically make sure that all TextViews have the same line height and spacing, independently of the content displayed inside them.

However, the TextViews containing arabic numbers / letters always occupy less space per line, which leads to a cumulated offset as shown in below screenshot:

How can I make secondTextView symmetric to firstTextView? Note that it is not possible to merge the two TextViews into one, I just provided a minimal simple sample here.

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        val firstTextView = findViewById<TextView>(R.id.firstText)
        val secondTextView = findViewById<TextView>(R.id.secondText)

        firstTextView.setText("২\n২\n২\n২\n২\n২\n২\n২")
        secondTextView.setText("2\n2\n2\n2\n2\n2\n2\n2")

        // Attempts
        TextViewCompat.setLineHeight(secondTextView, firstTextView.lineHeight)
        secondTextView.setLineSpacing(firstTextView.lineSpacingExtra, firstTextView.lineSpacingMultiplier)
        firstTextView.includeFontPadding = false
        secondTextView.includeFontPadding = false
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android=";
    xmlns:app=";
    xmlns:tools=";
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="16dp"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/firstText"
        android:paddingEnd="4dp"
        android:textSize="24sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/secondText"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@id/firstText"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

I am working on localizing my app into Bengal. I found that the Bengal numbers take up more line height than the arabic numbers do, and now I want to dynamically make sure that all TextViews have the same line height and spacing, independently of the content displayed inside them.

However, the TextViews containing arabic numbers / letters always occupy less space per line, which leads to a cumulated offset as shown in below screenshot:

How can I make secondTextView symmetric to firstTextView? Note that it is not possible to merge the two TextViews into one, I just provided a minimal simple sample here.

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        val firstTextView = findViewById<TextView>(R.id.firstText)
        val secondTextView = findViewById<TextView>(R.id.secondText)

        firstTextView.setText("২\n২\n২\n২\n২\n২\n২\n২")
        secondTextView.setText("2\n2\n2\n2\n2\n2\n2\n2")

        // Attempts
        TextViewCompat.setLineHeight(secondTextView, firstTextView.lineHeight)
        secondTextView.setLineSpacing(firstTextView.lineSpacingExtra, firstTextView.lineSpacingMultiplier)
        firstTextView.includeFontPadding = false
        secondTextView.includeFontPadding = false
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android/apk/res/android"
    xmlns:app="http://schemas.android/apk/res-auto"
    xmlns:tools="http://schemas.android/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="16dp"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/firstText"
        android:paddingEnd="4dp"
        android:textSize="24sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/secondText"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@id/firstText"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Share Improve this question edited Mar 28 at 6:30 BenjyTec asked Mar 27 at 11:48 BenjyTecBenjyTec 11.1k4 gold badges23 silver badges50 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I ended up manually checking the height of both TextViews and then using setLineSpacing to compensate for any height difference:

val mainView = findViewById<ContraintLayout>(R.id.main)
mainView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
    override fun onGlobalLayout() {
        val firstHeight = firstTextView.height
        val secondHeight = secondTextView.height
        val lineCount = firstTextView.lineCount

        if (lineCount > 0 && firstHeight > secondHeight) {
            val heightRatio = firstHeight.toFloat() / secondHeight.toFloat()
            secondTextView.setLineSpacing(0f, heightRatio)
            mainView.viewTreeObserver.removeOnGlobalLayoutListener(this)
        }
    }
})

It might depend on the total number of lines of the TextViews how well it works, as there is a rounding error cumulating. If you have many lines, you need to consider a more layout-based approach like using individual TextViews per line and then aliging these, for example by using a GridLayout.

发布评论

评论列表(0)

  1. 暂无评论