天天看點

自動調節字型大小的TextView自動調節字型大小的TextView

自動調節字型大小的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);
            }
        }
    }


}