如何实现两个TextView并排且根据内容自适应扩展的布局?
解决方案:用FlexboxLayout实现动态并排TextView
要实现两个内容完全动态的TextView并排且自适应换行、垂直居中,FlexboxLayout是最稳定的方案(Google官方维护的库),无需手动调整属性即可适配所有场景。
步骤1:添加依赖
在Module级别的build.gradle中引入Flexbox库:
implementation 'com.google.android:flexbox:2.0.1'
步骤2:编写布局XML
<?xml version="1.0" encoding="utf-8"?> <com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" app:flexDirection="row" app:alignItems="center"> <TextView android:id="@+id/tv_first" android:layout_width="0dp" android:layout_height="wrap_content" android:text="第一个很长很长很长很长很长很长很长很长很长很长的文本内容,需要换行显示" android:textSize="16sp" app:flexGrow="1" app:flexShrink="1"/> <TextView android:id="@+id/tv_second" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="第二个短文本" android:textSize="16sp" android:layout_marginStart="8dp" app:flexShrink="1"/> </com.google.android.flexbox.FlexboxLayout>
属性说明
- FlexboxLayout:
flexDirection="row":水平排列两个TextViewalignItems="center":垂直方向上两个文本居中对齐,满足“中间对齐”需求
- 第一个TextView:
layout_width="0dp"+flexGrow="1":自动占据父容器中除第二个TextView外的所有可用空间,内容过长时自动换行flexShrink="1":允许空间不足时收缩(配合内容自动换行)
- 第二个TextView:
layout_width="wrap_content":根据自身内容宽度自适应flexShrink="1":内容过长时自动换行layout_marginStart="8dp":添加两个文本间的间距,提升可读性
适配场景验证
- 第一个文本长、第二个短:第一个TextView占据大部分宽度换行,第二个短文本在同一行右侧显示
- 第一个文本短、第二个长:第一个文本靠左,第二个TextView占据剩余空间自动换行
- 两个文本均长:两个TextView各占部分可用宽度,同时换行,保持垂直居中对齐
原生布局备选方案(无第三方库)
如果无法引入FlexboxLayout,需通过代码动态测量文本宽度并调整布局参数:
// 测量文本宽度 fun measureTextWidth(text: String, textSize: Float): Float { val paint = Paint() paint.textSize = textSize return paint.measureText(text) } // 在View绘制完成后执行(可通过view.post{}调用) val parentWidth = parentView.width - parentView.paddingLeft - parentView.paddingRight val firstTextWidth = measureTextWidth(tv_first.text.toString(), tv_first.textSize) val secondTextWidth = measureTextWidth(tv_second.text.toString(), tv_second.textSize) val spacing = resources.getDimensionPixelSize(R.dimen.text_spacing) val layoutParamsFirst = tv_first.layoutParams as LinearLayout.LayoutParams val layoutParamsSecond = tv_second.layoutParams as LinearLayout.LayoutParams if (firstTextWidth + secondTextWidth + spacing <= parentWidth) { // 两个文本能并排显示,设为wrap_content layoutParamsFirst.width = LinearLayout.LayoutParams.WRAP_CONTENT layoutParamsSecond.width = LinearLayout.LayoutParams.WRAP_CONTENT } else { // 空间不足,分配宽度让文本换行 if (firstTextWidth > parentWidth - secondTextWidth - spacing) { layoutParamsFirst.width = parentWidth - secondTextWidth.toInt() - spacing layoutParamsSecond.width = LinearLayout.LayoutParams.WRAP_CONTENT } else if (secondTextWidth > parentWidth - firstTextWidth - spacing) { layoutParamsSecond.width = parentWidth - firstTextWidth.toInt() - spacing layoutParamsFirst.width = LinearLayout.LayoutParams.WRAP_CONTENT } else { // 两个文本都过长,平分宽度 layoutParamsFirst.width = parentWidth / 2 layoutParamsSecond.width = parentWidth / 2 - spacing } } tv_first.layoutParams = layoutParamsFirst tv_second.layoutParams = layoutParamsSecond
内容的提问来源于stack exchange,提问作者Andrzej Zabost
相关产品推荐
相关产品推荐

