问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

自定义TextView:解决Android字体适配难题

创作时间:
作者:
@小白创作中心

自定义TextView:解决Android字体适配难题

引用
CSDN
8
来源
1.
https://blog.csdn.net/u010126792/article/details/89151373
2.
https://blog.csdn.net/qq_35644925/article/details/125222910
3.
https://blog.csdn.net/chuyouyinghe/article/details/125366927
4.
https://www.cnblogs.com/qylost/articles/11430709.html
5.
https://juejin.cn/post/7106714269730914312
6.
https://juejin.cn/post/6991637697924169742
7.
http://leaking.github.io/android/(customView)onMeasure/
8.
https://juejin.cn/post/6844903509901459470

在Android开发中,TextView是最常用的控件之一,用于显示文本信息。然而,在不同设备上,屏幕尺寸和分辨率的差异可能导致TextView的显示效果不尽如人意。本文将详细介绍如何通过自定义TextView来实现字体大小的自动适配,让应用在各种设备上都能保持良好的显示效果。

MeasureSpec原理简介

在深入自定义TextView之前,我们先了解一下MeasureSpec的概念。MeasureSpec是Android系统用来描述View尺寸的机制,它包含了尺寸和模式两部分信息:

  • EXACTLY:精确模式,表示父布局已经确定了View的大小,如使用match_parent或具体数值。
  • AT_MOST:最大值模式,表示View的大小不能超过父布局的限制,如使用wrap_content
  • UNSPECIFIED:未指定模式,通常用于系统内部测量。

自定义TextView实现

1. 创建自定义TextView类

我们需要继承View类,并实现基本的构造函数:

public class CustomTextView extends View {
    private float textSize;
    private String text;
    private int textColor;
    private Paint textPaint;
    private int gravity;

    public CustomTextView(Context context) {
        super(context);
        init();
    }

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 15, getContext().getResources().getDisplayMetrics());
        textColor = Color.BLACK;
        textPaint = new Paint();
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
        gravity = Gravity.CENTER;
    }
}

2. 重写onMeasure方法

这是实现自适应的关键步骤。我们需要根据MeasureSpec计算TextView的尺寸:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int wMode = MeasureSpec.getMode(widthMeasureSpec);
    int w = MeasureSpec.getSize(widthMeasureSpec);
    int hMode = MeasureSpec.getMode(heightMeasureSpec);
    int h = MeasureSpec.getSize(heightMeasureSpec);

    int contentWidth = 0;
    int contentHeight = 0;

    if (text != null && text.length() > 0) {
        Rect textSize = measureTextSize();
        contentWidth = textSize.width();
        contentHeight = textSize.height();
    }

    if (wMode == MeasureSpec.AT_MOST || wMode == MeasureSpec.UNSPECIFIED) {
        w = contentWidth;
    }
    if (hMode == MeasureSpec.AT_MOST || hMode == MeasureSpec.UNSPECIFIED) {
        h = contentHeight;
    }

    setMeasuredDimension(w, h);
}

private Rect measureTextSize() {
    Paint paint = new Paint();
    Rect textSize = new Rect();
    paint.setTextSize(textSize);
    paint.getTextBounds(text, 0, text.length(), textSize);
    return textSize;
}

使用Autosizing方式

Android系统提供了更简便的Autosizing方式,可以在xml中直接配置:

<TextView
    android:layout_width="340dp"
    android:layout_height="50dp"
    android:background="@drawable/shape_bg_008577"
    android:gravity="center_vertical"
    android:maxLines="1"
    android:text="这是标题,该标题的名字比较长,产品要求不换行全部显示出来"
    android:textSize="18sp"
    android:autoSizeTextType="uniform"
    android:autoSizeMaxTextSize="18sp"
    android:autoSizeMinTextSize="10sp"
    android:autoSizeStepGranularity="1sp"/>

或者在Java代码中设置:

TextView tvText = findViewById(R.id.tv_text);
TextViewCompat.setAutoSizeTextTypeWithDefaults(tvText, TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(tvText, 10, 18, 1, TypedValue.COMPLEX_UNIT_SP);

工具类实现非固定宽度适配

对于非固定宽度的适配,我们可以编写一个工具类来动态调整字体大小:

public void adjustTvTextSize(TextView tv, int maxWidth, String text) {
    int avaiWidth = maxWidth - tv.getPaddingLeft() - tv.getPaddingRight();

    if (avaiWidth <= 0) {
        return;
    }

    TextPaint textPaintClone = new TextPaint(tv.getPaint());
    float trySize = textPaintClone.getTextSize();

    while (textPaintClone.measureText(text) > avaiWidth && trySize > 8) {
        trySize -= 1;
        textPaintClone.setTextSize(trySize);
    }

    tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, trySize);
}

总结

通过以上三种方式,我们可以灵活应对不同场景下的TextView字体适配问题:

  • 自定义View方式适用于需要高度自定义的场景
  • Autosizing方式简单易用,适合大多数情况
  • 工具类方式则提供了更大的灵活性,特别是在宽度不固定的情况下

开发者可以根据具体需求选择最适合的方案,确保应用在各种设备上都能保持良好的显示效果。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号