Android开发:如何将一个TextView的行高配置复制到另一个?
解决孟加拉语数字与阿拉伯数字TextView行高不一致导致的偏移问题
问题背景
应用本地化到孟加拉语时,发现孟加拉数字(如২)的行高显著大于阿拉伯数字(如2)。即便尝试统一行高和间距,阿拉伯数字TextView的每行占用空间更小,会出现累积偏移,需让两个TextView保持上下对称,且无法合并为一个组件。
解决方案
方案1:统一行高+文本垂直对齐+布局后动态设置
核心思路是关闭字体默认内边距,强制文本垂直居中,等待布局完成后获取孟加拉语TextView的准确行高,再同步给阿拉伯数字TextView:
修改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") // 关闭字体默认上下内边距,消除额外空间差异 firstTextView.includeFontPadding = false secondTextView.includeFontPadding = false // 设置文本垂直居中,确保每行内容对齐 firstTextView.gravity = Gravity.CENTER_VERTICAL secondTextView.gravity = Gravity.CENTER_VERTICAL // 等待视图布局完成后,获取准确行高并统一设置 firstTextView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { firstTextView.viewTreeObserver.removeOnGlobalLayoutListener(this) val fixedLineHeight = firstTextView.lineHeight TextViewCompat.setLineHeight(firstTextView, fixedLineHeight) TextViewCompat.setLineHeight(secondTextView, fixedLineHeight) } }) } }
方案2:布局约束强制高度匹配
在布局文件中添加双向高度约束,确保两个TextView总高度完全一致,进一步消除累积偏移:
修改activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/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" app:layout_constraintBottom_toBottomOf="@id/secondText"/> <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" app:layout_constraintBottom_toBottomOf="@id/firstText"/> </androidx.constraintlayout.widget.ConstraintLayout>
方案3:自定义TextView强制固定行高(极端场景)
若上述方案仍有差异,可自定义TextView重写测量逻辑,彻底忽略字体自身的行高计算:
class FixedLineHeightTextView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.textViewStyle ) : TextView(context, attrs, defStyleAttr) { var fixedLineHeight: Int = 0 override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) if (fixedLineHeight > 0) { val totalHeight = fixedLineHeight * lineCount + compoundPaddingTop + compoundPaddingBottom setMeasuredDimension(measuredWidth, totalHeight) } } override fun getLineHeight(): Int { return if (fixedLineHeight > 0) fixedLineHeight else super.getLineHeight() } }
布局中替换为自定义TextView后,在代码中设置固定行高:
val firstTextView = findViewById<FixedLineHeightTextView>(R.id.firstText) val secondTextView = findViewById<FixedLineHeightTextView>(R.id.secondText) // ... 初始化文本后 firstTextView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { firstTextView.viewTreeObserver.removeOnGlobalLayoutListener(this) val fixedHeight = firstTextView.lineHeight firstTextView.fixedLineHeight = fixedHeight secondTextView.fixedLineHeight = fixedHeight firstTextView.requestLayout() secondTextView.requestLayout() } })
内容的提问来源于stack exchange,提问作者BenjyTec
相关产品推荐
相关产品推荐

