如何在包含不同字体大小的文本的 TextView 中垂直居中文本?

4

我的布局中有一个TextView,其中包含不同大小的文本:

enter image description here

这是通过使用SpannableString实现的:

SpannableString spannableString = new SpannableString("$20 Rewards");
    spannableString.setSpan(
            new AbsoluteSizeSpan(getResources().getDimensionPixelSize(R.dimen.textSize_16)), 0,
            3, 0);

    textView.setText(spannableString);

我的问题是,如您在上面的图片中所见,较小的文本无法垂直居中。我已经将android:gravity="center_vertical"添加到TextView中,但没有效果:

<TextView
    android:id="@+id/tv_hotel_rewards"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="8dp"
    android:background="@drawable/bg_dark_blue_partial_round"
    android:gravity="center_vertical"
    android:paddingBottom="4dp"
    android:paddingEnd="8dp"
    android:paddingStart="8dp"
    android:paddingTop="4dp"
    android:textColor="@color/white"
    android:textSize="@dimen/textSize_12"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/tv_hotel_price"
    tools:text="$140 Rewards"/>

有人知道如何使用单个TextView将其垂直居中或者是否可能实现吗?

1个回答

10

默认情况下,TextView 会在同一基线上绘制其中的所有文本。然而,您可以使用 MetricAffectingSpan 来修改特定字符的基线。通过将 span 应用于所有“小”文本,您可以将其基线向上移动,使其垂直居中显示。

public class CenterVerticalSpan extends MetricAffectingSpan {

    @Override
    public void updateMeasureState(@NonNull TextPaint textPaint) {
        textPaint.baselineShift += getBaselineShift(textPaint);
    }

    @Override
    public void updateDrawState(TextPaint textPaint) {
        textPaint.baselineShift += getBaselineShift(textPaint);
    }

    private int getBaselineShift(TextPaint tp) {
        float total = tp.ascent() + tp.descent();
        return (int) (total / 2f);
    }
}

SpannableString spannableString = new SpannableString("$20 Rewards");
spannableString.setSpan(new AbsoluteSizeSpan(fontSize), 0, 3, 0);
spannableString.setSpan(new CenterVerticalSpan(), 3, spannableString.length(), 0);

enter image description here


非常好的答案,对我的情况起作用了。我在左边有一个普通文本,在右边有一个ImageSpan(比文本大小稍大一点)。我不得不将CenterVerticalSpan设置为文本,之后它就垂直对齐到ImageSpan的中心。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接