Flutter 文本解读 10 | Icon 组件源码解读
source link: https://mp.weixin.qq.com/s?__biz=MzI0NjU3MDA4NQ%3D%3D&%3Bmid=2247484474&%3Bidx=1&%3Bsn=6ee79b93556990c1354b86a768252f57
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
零、前言
1.前情回顾
通过上两篇 Icon 相关的文章,我们大概认识了一下 Icon
类的构成。并通过自己写的小脚本,运行生成相关的 dart 文件及配置 yaml,解决了自定义图标字体的麻烦。本篇将详细地看一下 Icon
的源码,并介绍一下 Icon
主题相关的知识。
2.本系列其他文章
-
《Flutter 文本解读 7 | RichText 写个代码高亮组件》
-
《Flutter 文本解读 8 | Icon 与 RichText 的渊源》
-
《Flutter 文本解读 9 | Icon 与 RichText 的渊源》
一、Icon#build 分析
1. textDirection 属性
和 Text
组件一样, Icon
也必须保证 textDirection
属性的存在或有上级 Directionality
组件。否则 debugCheckHasDirectionality
方法会抛异常。如果 Icon
的 textDirection
属性为空,会通过上下文向上查找 Directionality
组件,并获取其存储的数据作为 textDirection
值。
2.图标主题 IconTheme
IconTheme
作为一个 InheritedWidget
,存储着默认的 图标主题数据 IconThemeData
。其中包括 颜色
、 透明度
、 尺寸
三个属性。如下图,可以看出 图标默认大小为 24,颜色 0xdd000000
1class IconThemeData with Diagnosticable {
2 const IconThemeData({this.color, double opacity, this.size}) : _opacity = opacity;
3
4 const IconThemeData.fallback()
5 : color = const Color(0xFF000000),
6 _opacity = 1.0,
7 size = 24.0;
8 //略...
3.当 icon 图标数据为空
当 icon
为空时,会返回使用 SizeBox
,宽高为 iconSize
。
也就是说: 即使没有设置图标数据,Icon 组件也会通过 SizedBox占据布局空间
,如下所示:
4.图标的透明度
IconTheme
默认给的图标颜色是 有透明度的
,当 iconTheme.opacity
非 1 时,会取 颜色透明度
和 主题透明度之积
。
如下,左边是 默认颜色
, 中间是 黑色
,右边是图标主题 0.6
的透明度。
5.Icon 组件的显示核心
这里通过 RichText
为 iconWidget
赋值,文本内容通过 String.fromCharCode(icon.codePoint)
在 icon.fontFamily
字体文件中寻找到对应的 Unicode
,可见图标字体的显示,本质上来说就是字符串的显示。
接下来有个 icon.matchTextDirection
的判断,当 textDirection = TextDirection.rtl
时,会通过 Transform
组件将 iconWidget
沿中心镜像反转一下。
测试如下, matchTextDirection
是 IconData
类的属性,想要设置,就需要自己构造。两个图标一样,当 textDirection = TextDirection.rtl
且 matchTextDirection = true
时,就会镜像一下。这时,举一反三,你应该能意识到,以后想要让一个组件镜像反转该如何去做。
Icons
中定义的
IconData
常量,有些是定义了
matchTextDirection = true
的,这样使用时就可以通过
TextDirection.rtl
进行图标镜像。
最后,通过 SizedBox + Center
组件为 iconWidget
设置尺寸并居中显示。到此 Icon
的源码就讲完了。
二、IconTheme 的使用
1.提供默认属性
通过上面 Icon
的源码可以看出, IconTheme
组件可以决定其后续节点中 Icon 组件的默认样式, 大小
、 颜色
、 透明度
。这样对应一批类似的 Icon
而言,就无须一个个地进行设置。
下图左右的效果一样,提供 IconTheme
可以设置默认属性,避免右侧这样的代码冗余。
2.IconTheme 起作用的原理
这和 DefaultTextStyle
原理是一样的,IconTheme 是一个 InheritedWidget
,其内部存储 IconThemeData
数据,提供 IconTheme.of
方法,通过上下文,向上层根据 IconTheme
类型查找数据。如下,在 Wrap
外层包裹 IconTheme
,当 Icon
构建时,会往上层寻找 IconTheme
存储的数据。这里我们自己设置了,就会访问到设置的 IconTheme
,而发挥效果。
在 Element#dependOnInheritedWidgetOfExactType
中。可以通过类型,获取到对应的 InheritedElement
。
再通过 Element#dependOnInheritedElement
获取元素对应的组件,即这里的 IconThem
,从而实现数据在后续节点中的共享。
3.默认图标主题设置的时机
1MaterialApp --> AnimatedTheme --> Theme --> IconTheme
MaterialApp
中使用了 AnimatedTheme
。
AnimatedTheme
中使用了 Theme
。
Theme
中使用了 IconTheme
,其中的图标主题的数据为 ThemeData.iconTheme
。
在 ThemeData
中当 isDark
时,图标颜色为白色,否则为 blake87
,这也是为什么图标颜色默认有透明度的根本原因。
这样,Icon 组件的源码就讲完了,本文结束,谢谢观看 ~
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK