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()设置
网友评论