概述:TextView字体大小自适应,autoSize属性使用
使用方法
在xml中设置AutoSizeing属性
在xml中按如下示例设置autoSize属性即可
<androidx.appcompat.widget.AppCompatTextView
app:autoSizeTextType="uniform"
app:autoSizeMaxTextSize="30dp"
app:autoSizeMinTextSize="11dp"
app:autoSizeStepGranularity="1px"
app:autoSizeTextType="uniform" 表示使用AutoSizeing属性,自适应调整字体大小;none表示不使用,默认是none
app:autoSizeMaxTextSize 设置最大的TextSize,默认是112sp
app:autoSizeMinTextSize 设置最小的TextSize,默认是12sp
app:autoSizeStepGranularity 设置字体大小变更粒度1px
app:autoSizeMaxTextSize 设置字体大小变更数组,字体大小变更范围从这个数组中取,这个很少应用到。
代码设置AutoSizeing属性
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(textView, minTextSize, maxTextSize, autoSizeStepGranularity, TypedValue.COMPLEX_UNIT_PX);
备注:使用该API时,建议单位使用 TypedValue.COMPLEX_UNIT_PX, 因为如果设置为DP、SP,会影响textSize变更粒度,默认是1px.
/*
* @attr name android:autoSizeTextType
* @attr name android:autoSizeTextType
* @attr name android:autoSizeMinTextSize
* @attr name android:autoSizeMaxTextSize
* @attr name android:autoSizeStepGranularity
*/
public static void setAutoSizeTextTypeUniformWithConfiguration(
@NonNull TextView textView,
int autoSizeMinTextSize,
int autoSizeMaxTextSize,
int autoSizeStepGranularity,
int unit) {
示例:
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(textView, 3, 16, 1, TypedValue.COMPLEX_UNIT_SP);
默认值
//默认最小字体大小 12sp
// Default minimum size for auto-sizing text in scaled pixels.
private static final int DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP = 12;
//默认最大字体大小 112sp
// Default maximum size for auto-sizing text in scaled pixels.
private static final int DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP = 112;
// Default value for the step size in pixels.
private static final int DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX = 1;
textSize适配原理
如下方法是计算文本容纳在该TextView的最大文本大小。 通过minTextSize、maxTextSize和最小变更粒度,计算出textSize变更集合mAutoSizeTextSizesInPx,该数组对应的单位是px。形参 availableSpace 是文本可绘制区域,最后通过二分法,在mAutoSizeTextSizesInPx数组中找到最大的文本大小。
/**
* 执行二进制搜索,以查找仍能容纳在该大小内的最大文本大小
* availableSpace 字体可绘制区域,则TextView实际宽高决定
* Performs a binary search to find the largest text size that will still fit within the size
* available to this view.
*/
private int findLargestTextSizeWhichFits(RectF availableSpace) {
//textSize集合
final int sizesCount = mAutoSizeTextSizesInPx.length;
if (sizesCount == 0) {
throw new IllegalStateException("No available text sizes to choose from.");
}
int bestSizeIndex = 0;
int lowIndex = bestSizeIndex + 1;
int highIndex = sizesCount - 1;
int sizeToTryIndex;
//二分法,从数组中找到最合适的textSize
while (lowIndex <= highIndex) {
sizeToTryIndex = (lowIndex + highIndex) / 2;
if (suggestedSizeFitsInSpace(mAutoSizeTextSizesInPx[sizeToTryIndex], availableSpace)) {
bestSizeIndex = lowIndex;
lowIndex = sizeToTryIndex + 1;
} else {
highIndex = sizeToTryIndex - 1;
bestSizeIndex = highIndex;
}
}
return mAutoSizeTextSizesInPx[bestSizeIndex];
}
注意事项:
1.兼容性问题,8.0以下系统不生效
autoSizeMaxTextSize等属性必须使用自定义名称空间,如上使用 app:autoSizeMaxTextSize ,而不能使用 android:autoSizeMaxTextSize。TextView也要替换成 androidx.appcompat.widget.AppCompatTextView 。这是因为AutoSizeing属性是8.0及以后支持的,在系统8.0以前,是没有原生 android:autoSize 属性的,所以必须使用自定义名称空间,否则在8.0以下系统不识别,相当于没有设置AutoSizeing属性。只要Activity继承的是AppCompatActivity,xml中TextView会被自动替换成AppCompatTextView。这里要将TextView替换成 AppCompatTextView 是因为使用app:autoSize...的属性是AppCompatTextView,TextView是没有的,防止在xml中报错。
2.代码规范
autoSizeMinTextSize和 autoSizeMaxTextSize 都要设置,尤其是autoSizeMaxTextSize,如果不设置,默认值是112sp,比较大,生成的适配字体大小的数组长度会很长。两个都是默认值,区间为100sp,变更粒度为1px,以现在主流DPI=480的手机来计算,默认scaleDensity=3.0,这个数组长度达到300。从资源和性能两方面都建议全部写上明确的 autoSizeMinTextSize和autoSizeMaxTextSize。
3. 设置autoSizeing属性注意事项
在计算textSize时,首页需要确定TextView的宽高,宽高确定之后,再计算最大的TextSize。 当android:lines="1", android:layout_height="wrap_content", 决定TextView高度的android:textSize属性值,如果没有设置,就是默认的14sp。再根据TextView的实际高度,计算文本容纳在该TextView的最大文本大小。
一般需求是:能放的下就按UI图上的字体大小显示,如果放不下就自动缩小。
textSize是由 TextView实际高度、行数和 autoSizeMaxTextSize 属性值来决定的。例如UI图设置字体大小为20sp,最多一行。如果设置android:textSize="14sp" (默认值),android:layout_height="wrap_content",那么该TextView的测量所需高度就是textSize=14sp时所需的高度,此时虽然 autoSizeMaxTextSize=20sp,但TextView实际高度是textSize=14sp对应的高度,所以实际上 maxTextSize只能是14sp,否则放不下文字。 autoSizeMaxTextSize 与 android:layout_height 配合使用时,autoSizeMaxTextSize是不会影响TextView高度的,影响TextView高度的是android:textSize属性。要想实现UI设计,需要将 android:textSize设置与 app:autoSizeMaxTextSize 保持一致,或者 android:layout_height 设置为match_parent or 具体的数值。