美文网首页
TextView的AutoSizeing的源码解析

TextView的AutoSizeing的源码解析

作者: code希必地 | 来源:发表于2020-08-24 17:53 被阅读0次

    1、前言

    AutoSizeing的使用非常简单,使用TextViewCompat中的一系列方法就能达到如下效果:


    autosizeing的效果.gif

    那么系统是如何实现的呢?其实就是根据TextView控件的宽高和TextView的文本内容来计算出一个合适的大小。

    2、AutoSizeing如何计算大小

    AutoSizeing是在Android8.0引入的,在Support V26中做了兼容,它们的实现方式基本一致,这里主要分析下Support V26中的计算方式。
    AutoSizeing实际修改TextView size的方法在AppCompatTextViewAutoSizeHelper中的setAutoSizeTextTypeWithDefaults()方法中

    void setAutoSizeTextTypeWithDefaults(@TextViewCompat.AutoSizeTextType int autoSizeTextType) {
            if (supportsAutoSizeText()) {
                switch (autoSizeTextType) {
                    case TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE:
                        clearAutoSizeConfiguration();
                        break;
                    case TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM:
                        final DisplayMetrics displayMetrics =
                                mContext.getResources().getDisplayMetrics();
                        final float autoSizeMinTextSizeInPx = TypedValue.applyDimension(
                                TypedValue.COMPLEX_UNIT_SP,
                                DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP,
                                displayMetrics);
                        final float autoSizeMaxTextSizeInPx = TypedValue.applyDimension(
                                TypedValue.COMPLEX_UNIT_SP,
                                DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP,
                                displayMetrics);
    
                        validateAndSetAutoSizeTextTypeUniformConfiguration(
                                autoSizeMinTextSizeInPx,
                                autoSizeMaxTextSizeInPx,
                                DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX);
                        if (setupAutoSizeText()) {
                            autoSizeText();
                        }
                        break;
                    default:
                        throw new IllegalArgumentException(
                                "Unknown auto-size text type: " + autoSizeTextType);
                }
            }
        }
    

    从源码中可以看出只有满足setupAutoSizeText()时,才会调用autoSizeText();去修改TextView的size。setupAutoSizeText()方法主要作用是在没有预设尺寸数组时,根据

    mAutoSizeMinTextSizeInPx=DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP;//12
    mAutoSizeStepGranularityInPx=DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX;//1
    mAutoSizeMaxTextSizeInPx=DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP;//112
    

    为mAutoSizeTextSizesInPx数组填充数据。此数据在findLargestTextSizeWhichFits()方法中使用。
    核心的计算是在autoSizeText();方法中。

    void autoSizeText() {
            if (!isAutoSizeEnabled()) {
                return;
            }
    
            if (mNeedsAutoSizeText) {
                if (mTextView.getMeasuredHeight() <= 0 || mTextView.getMeasuredWidth() <= 0) {
                    return;
                }
    
                final boolean horizontallyScrolling = invokeAndReturnWithDefault(
                        mTextView, "getHorizontallyScrolling", false);
                final int availableWidth = horizontallyScrolling
                        ? VERY_WIDE
                        : mTextView.getMeasuredWidth() - mTextView.getTotalPaddingLeft()
                                - mTextView.getTotalPaddingRight();
                final int availableHeight = mTextView.getHeight() - mTextView.getCompoundPaddingBottom()
                        - mTextView.getCompoundPaddingTop();
    
                if (availableWidth <= 0 || availableHeight <= 0) {
                    return;
                }
    
                synchronized (TEMP_RECTF) {
                    TEMP_RECTF.setEmpty();
                    TEMP_RECTF.right = availableWidth;
                    TEMP_RECTF.bottom = availableHeight;
                    final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF);
                    if (optimalTextSize != mTextView.getTextSize()) {
                        setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize);
                    }
                }
            }
            // Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing
            // after the next layout pass should set this to false.
            mNeedsAutoSizeText = true;
        }
    

    代码很简单,主要逻辑如下:

    • 1、使用isAutoSizeEnabled()判断是否开启了AutoSizeing
    • 2、判断mNeedsAutoSizeText是否为true,mNeedsAutoSizeText表示是否存在可变动的textSize数组。
    • 3、计算TextView本身的区域大小,存放在TEMP_RECTF中
    • 4、使用findLargestTextSizeWhichFits()方法计算出一个合适的textSize,其实就是通过遍历可变textSize数组,然后通过创建StaticLayout,使用StaticLayout的方法来计算出满足条件的textSize。只不过其中为了效率使用二分法查找的方式。
    • 5、如果计算出的textSize和当前的textSize不一致就通过setTextSizeInternal()设置

    相关文章

      网友评论

          本文标题:TextView的AutoSizeing的源码解析

          本文链接:https://www.haomeiwen.com/subject/rpmnjktx.html