如何在包含不同字号文本的TextView中实现文本垂直居中?
解决单个TextView内不同字号文本垂直居中问题
这个问题其实很常见——当用SpannableString给TextView设置不同字号时,默认的基线对齐会导致小字号文本看起来偏下,即使给TextView加了android:gravity="center_vertical"也没用,因为这个属性是控制整个TextView内容的对齐,而非内部不同Span的对齐。
下面给你两种可行的解决方法:
方法一:自定义Span实现垂直居中
你可以写一个自定义的MetricAffectingSpan,手动调整小字号文本的基线位置,让它和大字号文本垂直居中对齐。
步骤1:创建自定义Span类
public class VerticalCenterSpan extends MetricAffectingSpan { @Override public void updateDrawState(TextPaint textPaint) { // 计算当前文本的垂直偏移量,使其居中 FontMetricsInt fontMetrics = textPaint.getFontMetricsInt(); // 计算文本中心到基线的距离 int centerOffset = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom; textPaint.baselineShift += centerOffset; } @Override public void updateMeasureState(TextPaint textPaint) { updateDrawState(textPaint); } }
步骤2:同时应用两个Span
在设置AbsoluteSizeSpan的同时,给小字号的文本部分加上这个自定义Span:
SpannableString spannableString = new SpannableString("$20 Rewards"); // 设置大字号($20) spannableString.setSpan( new AbsoluteSizeSpan(getResources().getDimensionPixelSize(R.dimen.textSize_16)), 0, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE ); // 设置小字号并垂直居中(Rewards) spannableString.setSpan( new AbsoluteSizeSpan(getResources().getDimensionPixelSize(R.dimen.textSize_12)), 3, spannableString.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE ); spannableString.setSpan( new VerticalCenterSpan(), 3, spannableString.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE ); textView.setText(spannableString);
方法二:使用两个TextView(更简单直观)
如果不想写自定义Span,直接用两个TextView包裹在一个LinearLayout里,通过布局属性实现垂直居中,这种方法更易维护:
布局代码示例
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" android:background="@drawable/bg_dark_blue_partial_round" android:padding="4dp" android:paddingStart="8dp" android:paddingEnd="8dp"> <TextView android:id="@+id/tv_rewards_amount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="$20" android:textColor="@color/white" android:textSize="@dimen/textSize_16"/> <TextView android:id="@+id/tv_rewards_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" Rewards" android:textColor="@color/white" android:textSize="@dimen/textSize_12"/> </LinearLayout>
这种方法不需要处理Span的对齐问题,通过LinearLayout的gravity="center_vertical"就能让两个TextView完美垂直居中,后期修改字号或文本也更方便。
两种方法各有优劣:自定义Span适合必须用单个TextView的场景(比如需要文本选中、复制等交互),而双TextView方案更简单,适合大多数布局场景。
内容的提问来源于stack exchange,提问作者Mateus Gondim
相关产品推荐
相关产品推荐

