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

时间:2018-01-16 15:24:41

标签: android textview spannablestring

我的布局中有一个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 个答案:

答案 0 :(得分:0)

默认情况下,TextView将在同一基线上绘制其中的所有文本。但是,您可以使用MetricAffectingSpan来修改某些字符的基线。通过对所有“小”文本应用跨度,可以将其基线向上移动,使其垂直居中。

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