12

Flutter 文本解读 10 | Icon 组件源码解读

 3 years ago
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.本系列其他文章

一、Icon#build 分析

1. textDirection 属性

Text 组件一样, Icon 也必须保证 textDirection 属性的存在或有上级 Directionality 组件。否则 debugCheckHasDirectionality 方法会抛异常。如果 Icon 的   textDirection 属性为空,会通过上下文向上查找 Directionality 组件,并获取其存储的数据作为 textDirection 值。

EJVRFjb.png!mobile

2.图标主题 IconTheme

IconTheme 作为一个 InheritedWidget ,存储着默认的 图标主题数据 IconThemeData 。其中包括 颜色透明度尺寸 三个属性。如下图,可以看出 图标默认大小为 24,颜色 0xdd000000

a2qi6v3.png!mobile

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

NZF7Bn3.png!mobile

也就是说: 即使没有设置图标数据,Icon 组件也会通过 SizedBox占据布局空间 ,如下所示:

Rn67z2e.png!mobile

4.图标的透明度

IconTheme 默认给的图标颜色是 有透明度的 ,当 iconTheme.opacity 非 1 时,会取 颜色透明度主题透明度之积

6jM7Rvq.png!mobile

如下,左边是 默认颜色 , 中间是 黑色 ,右边是图标主题 0.6 的透明度。

yA3Mv2y.png!mobile

5.Icon 组件的显示核心

这里通过 RichTexticonWidget 赋值,文本内容通过 String.fromCharCode(icon.codePoint)icon.fontFamily 字体文件中寻找到对应的 Unicode ,可见图标字体的显示,本质上来说就是字符串的显示。

fMvQrqz.png!mobile

接下来有个 icon.matchTextDirection 的判断,当 textDirection = TextDirection.rtl 时,会通过 Transform 组件将 iconWidget 沿中心镜像反转一下。

YvYn63N.png!mobile

测试如下, matchTextDirectionIconData 类的属性,想要设置,就需要自己构造。两个图标一样,当 textDirection = TextDirection.rtlmatchTextDirection = true 时,就会镜像一下。这时,举一反三,你应该能意识到,以后想要让一个组件镜像反转该如何去做。

IriE7v6.png!mobile Icons 中定义的 IconData 常量,有些是定义了   matchTextDirection = true  的,这样使用时就可以通过 TextDirection.rtl 进行图标镜像。

最后,通过 SizedBox + Center 组件为 iconWidget 设置尺寸并居中显示。到此 Icon 的源码就讲完了。

zmUvyui.png!mobile

二、IconTheme 的使用

1.提供默认属性

通过上面 Icon 的源码可以看出, IconTheme 组件可以决定其后续节点中 Icon 组件的默认样式, 大小颜色透明度 。这样对应一批类似的 Icon 而言,就无须一个个地进行设置。

eeARZrn.png!mobile

下图左右的效果一样,提供 IconTheme 可以设置默认属性,避免右侧这样的代码冗余。

ERfeMv7.png!mobile

2.IconTheme 起作用的原理

这和 DefaultTextStyle 原理是一样的,IconTheme 是一个 InheritedWidget ,其内部存储 IconThemeData 数据,提供 IconTheme.of 方法,通过上下文,向上层根据 IconTheme 类型查找数据。如下,在 Wrap 外层包裹 IconTheme ,当 Icon 构建时,会往上层寻找 IconTheme 存储的数据。这里我们自己设置了,就会访问到设置的   IconTheme ,而发挥效果。

uAbiIjv.png!mobile

Element#dependOnInheritedWidgetOfExactType 中。可以通过类型,获取到对应的 InheritedElement

QZjq6vr.png!mobile

再通过 Element#dependOnInheritedElement 获取元素对应的组件,即这里的 IconThem ,从而实现数据在后续节点中的共享。

zqEjQzV.png!mobile

3.默认图标主题设置的时机

1MaterialApp --> AnimatedTheme --> Theme --> IconTheme

MaterialApp 中使用了 AnimatedTheme

RzIzYfZ.png!mobile

AnimatedTheme 中使用了 Theme

7fauEjM.png!mobile

Theme 中使用了 IconTheme ,其中的图标主题的数据为 ThemeData.iconTheme

Fz2URji.png!mobile

ThemeData 中当 isDark 时,图标颜色为白色,否则为 blake87 ,这也是为什么图标颜色默认有透明度的根本原因。

a6n2QrQ.png!mobile

这样,Icon 组件的源码就讲完了,本文结束,谢谢观看 ~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK