自动调节字体大小的TextView

本文记录了一个项目需求:当TextView文字过长时,优先通过缩小字体而非换行来适应宽度。原生的自动缩放以高度为标准,但这里自定义了一个View,实现了以宽度为基准的字体自动调节功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自动调节字体大小的TextView

今天项目中遇见一个需求,在此记录。
需求描述:TextView中text过长的时候,优先缩小字体,如果缩小字体依旧过长,再换行。
Google原生自动缩放是以高度作为标准的,只有高度不够时才会进行缩放。与我们需要以宽度为标准不同,故自定义View
自定义TextView代码如下:

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.TextView;



public class AutoTextView extends TextView {

    private float mTextSize;
    private float mMinSize;
    private float mSizeStep;
    private StaticLayout mStaticLayout;
    private TextPaint mTextPaint;

    public AutoTextView(Context context) {
        this(context, null);
    }

    public AutoTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AutoTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initialise(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        autoText(parentWidth, parentHeight);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    private void initialise(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.AuTotextView, defStyleAttr, 0);
        mMinSize = attr.getDimension(R.styleable.AuTotextView_autoSizeMinTextSize, 0);
        mSizeStep = attr.getDimension(R.styleable.AuTotextView_autoSizeStepGranularity, 0);
        attr.recycle();
        if (mMinSize == 0 && mSizeStep == 0) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                mMinSize = getAutoSizeMinTextSize();
                mSizeStep = getAutoSizeStepGranularity();
                setAutoSizeTextTypeWithDefaults(AUTO_SIZE_TEXT_TYPE_NONE);
            }
        }
        mTextPaint = new TextPaint();
        mTextPaint.set(this.getPaint());
        mTextSize = getTextSize();
    }



    /**
     * auto text size.
     *
     * @param parentWidth  parant layout can give the max width;
     * @param parentHeight parant layout can give the max height;
     */
    private void autoText(int parentWidth, int parentHeight) {
        int maxWidth = getMaxWidth();
        int maxHeight = getMaxHeight();
        if (maxWidth != -1 && maxWidth < parentWidth) {
            parentWidth = maxWidth;
        }
        if (maxHeight != -1 && maxHeight < parentHeight) {
            parentHeight = maxHeight;
        }
        int viewWidth = parentWidth - getTotalPaddingLeft()
                - getTotalPaddingRight();
        if (viewWidth < 0) {
            return;
        }
        if (mTextPaint == null) {
            mTextPaint = new TextPaint();
        }
        mTextPaint.set(getPaint());
        if (mMinSize > 0 && mSizeStep > 0) {
            float currentSize = mTextSize;
            CharSequence text = getText();
            mTextPaint.setTextSize(currentSize);
            float textWidth = mTextPaint.measureText(text.toString());
            while (textWidth > viewWidth && currentSize > mMinSize) {
                currentSize -= mSizeStep;
                mTextPaint.setTextSize(currentSize);
                textWidth = mTextPaint.measureText(text.toString());
            }
            setTextSize(TypedValue.COMPLEX_UNIT_PX, currentSize);
            measureHeight(parentHeight, parentWidth);
        }
    }

    private void measureHeight(int parentHeight, int parentWidth) {
        int maxLines = getMaxLines();
        if (maxLines > 1) {
            int viewWidth = parentWidth - getTotalPaddingLeft()
                    - getTotalPaddingRight();
            int extendedPaddingBottom = 0;
            int extendedPaddingTop = 0;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                extendedPaddingBottom = getExtendedPaddingBottom();
                extendedPaddingTop = getExtendedPaddingTop();
            }

            int availedHeight = parentHeight - extendedPaddingBottom - extendedPaddingTop;
            if (availedHeight <= 0) {
                return;
            }
            mStaticLayout = new StaticLayout(getText(), getPaint(),
                    viewWidth, Layout.Alignment.ALIGN_NORMAL,
                    getLineSpacingMultiplier(), getLineSpacingExtra(), false);
            int lineCount = mStaticLayout.getLineCount();
            if (mStaticLayout.getHeight() > availedHeight && lineCount > 1
                    && lineCount <= maxLines + 1) {
                setMaxLines(lineCount - 1);
            }
        }
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值