Hi,大家好,我是承香墨影!
前两天聊了一下 Autosizing 的使用,反映还不错。毕竟是这种能解决实际问题的新 Api,确实在需要的时候,用起来会很顺手。
简单回顾一下,Autosizing 是在 Support v26 中新支持的功能,可以根据文本的内容和 TextView 的大小,自动适应齐内部文本的字体大小,来达到完全显示的效果。而这个功能,最低能兼容到 Api Level 14,可以说是一个诚意满满的新 Api。
还不了解 Autosizing 的朋友,可以看看之前的文章《》,里面有使用它的详细介绍。
我想,在没有 Autosizing 的时候,应该已经有人以这样的思路在实现功能了。那么,今天就来从源码的角度分析一下,Autosizing 的原理如何,看看它是如何工作的。
二、带着问题看源码分析源码也是讲究方式方法的,我主推的一个思路,就是带着问题看源码。
很多大型项目,其实本身都是很复杂的,并且涵盖的功能点也非常的多,如果想要一次就把它完整的阅读屡清楚,还是很吃力的。
所以我建议在阅读开源项目之前,你先阅读文档,尝试使用一下它,看看它能做什么,再自己思考一下,如果你是作者,你会如何去实现这些功能的,最后带着这些问题去阅读源码,以问题为出发点,看看那些大牛写的优秀的开源库,到底有什么值得我们借鉴的地方。
总归一句话:阅读源码是为了更好的编写源码!
当我看到到 Autosizing 这个新特性的时候,我有一些好奇的地方在于:
Android 8.0 的 TextView 和 Support 包中,Autosizing 的实现,有什么区别?
Autosizing 是会在什么时机,去触发根据文本的内容,计算出一个适合的字体大小。
Autosizing 是如何计算合适的字体大小的。
脱离 Autosizing,源码中的功能,有什么能借鉴的使用场景。
大概就是这些问题吧,接下来我们看看 Autosizing 是如何实现的。
三、Autosizing 源码 3.1 实现的区别对于 Android 8.0 中和 Support v26 中,具体对于 Autosizing 的实现,有什么区别这一点,大致阅读一下两边的源码,你会发现大致上没区别。
它们之间,和 Autosizing 相关的源码所在的源码文件也不一样:
Android 8.0 主要在 TextView 中。
Support v26 主要在 AppCompatTextViewAutoSizeHelper。
随手比对一下它们的 setAutoSizeTextTypeWithDefaults() 方法,这个方法用来标记是否对 TextView 开启 Autosizing。
左边是 Android 8.0 的 TextView ,右边是 AppCompatTextViewAutoSizeHelper。
可以看到,整个代码的结构都是一致的,只是部分引用的类不一样而已,但是表达的意思是一致的。
之所以说它们之前大致是一样的,是因为有一些 Api 是 private 的或者被标记为 @hide 了,这样,在外部是无法访问到的。对此 AppCompatTextViewAutoSizeHelper 的做法是用反射的形式去调用它。
例如,实际去修改 TextView 尺寸的方法 autoSizeText() ,看下面它们的区别。
左边是 Android 8.0 的 TextView ,右边是 AppCompatTextViewAutoSizeHelper。
两边都需要获取 mHorizontallyScrolling 的值,TextView 内部当然可以直接调用了,而 AppCompatTextViewAutoSizeHelper 的做法是,使用 invokeAndReturnWithDefault() 方法,通过反射区获取这个值。
所以,我们可以得出结论,两边的实现思路,大体上是没有区别的,只是有一些小细节,会不一样,但是我们不需要太在意这些。
既然,两边的区别不大,之后我们就以 Support v26 中,关于 Autosizing 的源码实现来进行分析。
3.2 触发 Autosizing 的时机首先这个时机让我自己来设计,也非常好理解。
本质上 Autosizing 就是为了让 TextView 中的文本,能完全显示,在这个过程中会去调整 文本 的字体大小。
那这样,触发它的时机,其实就很容易猜到了:
在 文本内容 变动的时候。
在 TextView 大小变动的时候。
Support v26 中,之所以能保证兼容,本质上它会自动将 TextView 这样的控件,替换成 AppCompatTextView 来达到兼容的效果,这个过程中,开发者只需要使用 AppCompatActivity 就可以了,其它的不需要开发者来参与。这样,其实我们只需要关注 AppCompatTextView 中的实现逻辑就好了。
前面提到,操作 Autosizing 的具体源码,在 AppCompatTextViewAutoSizeHelper 中。 而 AppCompatTextView 并不直接操作它。