IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Flutter原理—布局绘制 -> 正文阅读

[移动开发]Flutter原理—布局绘制

真正的布局和大小计算等行为,都是在 RenderBox 上去实现的。 不同的 Widget 通过各自的 RenderBox 实现了“差异化”的布局效果。所以找每个 Widget 的实现,找它的 RenderBox 实现就可以了。

在这里插入图片描述

所以在 Flutter 中,最终页面的 Layout、Paint 等都会发生在 Widget 所对应的 RenderObject 子类中,而 RenderObject 也是 Flutter 跨平台的最大的特点之一:所有的控件都与平台无关 ,这里简单的人话就是: Flutter 只要求系统提供的 “Canvas”,然后开发者通过 Widget 生成 RenderObject “直接” 通过引擎绘制到屏幕上。

绘制过程

我们知道 Widget 最终都转化为 RenderObject , 所以了解绘制我们直接先看 RenderObject 的 paint 方法。

如下图所示,所有的 RenderObject 子类都必须实现 paint 方法,并且该方法并不是给用户直接调用,需要更新绘制时,你可以通过 markNeddsPaint 方法去触发界面绘制。

在这里插入图片描述

那么,按照“国际流程”,在经历大小和布局等位置计算之后,最终 paint 方法会被调用,该方法带有两个参数: PaintingContext 和 Offset ,它们就是完成绘制的关键所在,那么相信此时大家肯定有个疑问就是:

PaintingContext 是什么?
Offset 是什么?

通过飞速查阅源码,我们可以首先了解到有 :

PaintingContext 的关键是 A place to paint ,同时它在父类 ClipContext 是包含有 Canvas ,并且 PaintingContext 的构造方法是 @protected,只在 PaintingContext.repaintCompositedChild 和 pushLayer 时自动创建。

Offset 在 paint 中主要是提供当前控件在屏幕的相对偏移值,提供绘制时确定绘制的坐标。

在这里插入图片描述

OK,继续往下走,那么既然 PaintingContext 叫 Context ,那它肯定是存在上下文关系,那它是在哪里开始创建的呢?

通过调试源码可知,项目在 runApp 时通过 WidgetsFlutterBinding 启动,而在以前的篇幅中我们知道, WidgetsFlutterBinding 是一个“胶水类”,它会触发 mixin 的 RendererBinding ,如下图创建出根 node 的 PaintingContext 。

在这里插入图片描述

好了,那么Offset 呢?如下图,对于 Offset 的传递,是通过父控件和子控件的 offset 相加之后,一级一级的将需要绘制的坐标结合去传递的。

目前简单来说,通过 PaintingContext 和 Offset ,在布局之后我们就可以在屏幕上准确的地方绘制会需要的画面。

在这里插入图片描述

测试绘制

这里我们先做一个有趣的测试。
我们现在屏幕上通过 Container 限制一个高为 60 的绿色容器,如下图,暂时忽略容器内的 Slider 控件 ,我们图中绘制了一个 100 x 100 的红色方块,这时候我们会看到下图右边的效果是:纳尼?为什么只有这么小?
事实上,因为正常 Flutter 在绘制 Container 的时候,AppBar 已经帮我们计算了状态栏和标题栏高度偏差,但我们这里在用 Canvas 时直接粗暴的 drawRect,绘制出来的红色小方框,左部和顶部起点均为0,其实是从状态栏开始计算绘制的。

在这里插入图片描述

那如果我们调整位置呢?把起点 top 调整到 300,出现了如下图的效果:纳尼?红色小方块居然画出去了,明明 Container 只有绿色的大小。

在这里插入图片描述

其实这里的问题还是在于 PaintingContext ,它有一个参数是 estimatedBounds ,而 estimatedBounds 正常是在创建时通过 child.paintBounds 赋值的,但是对于 estimatedBounds 还有如下的描述:原来画出去也是可以。

The canvas will allow painting outside these bounds.
The [estimatedBounds] rectangle is in the [canvas] coordinate system.


所以到这里你可以通俗的总结, 对于 Flutter 而言,整个屏幕都是一块画布,我们通过各种 Offset 和 Rect 确定了位置,然后通过 PaintingContext 的Canvas 绘制上去,目标是整个屏幕区域,整个屏幕就是一帧,每次改变都是重新绘制。

RepaintBoundary
我们先从 markNeedsPaint() 开始, 总结出其大致流程如下图,可以看到 markNeedsPaint 在 requestVisualUpdate 时确实触发了引擎去更新绘制界面。

在这里插入图片描述

当调用 markNeedsPaint() 时,RenderObject 就会往上的父节点去查找,根据 isRepaintBoundary 是否为 true,会决定是否从这里开始去触发重绘。换个说法就是,确定要更新哪些区域。

所以其实流程应该是:通过isRepaintBoundary 往上确定了更新区域,通过 requestVisualUpdate 方法触发更新往下绘制。

在这里插入图片描述

并且从源码中可以看出, isRepaintBoundary 只有 get ,所以它只能被子类 override ,由子类表明是否是为重绘的边缘,比如 RenderProxyBox 、RenderView 、RenderFlow 等 RenderObject 的 isRepaintBoundary 都是 true。
所以如果一个区域绘制很频繁,且可以不影响父控件的情况下,其实可以将 override isRepaintBoundary 为 true。

Layer

当 isRepaintBoundary 为 true 时,那么该区域就是一个可更新绘制区域,而当这个区域形成时, 其实就会新创建一个 Layer 。

不同的 Layer 下的 RenderObject 是可以独立的工作,比如 OffsetLayer 就在 RenderObject 中用到,它就是用来做定位绘制的。

在这里插入图片描述

同时这也引生出了一个结论:不是每个 RenderObject 都具有 Layer 的,因为这受 isRepaintBoundary 的影响。

其次在 RenderObject 中还有一个属性叫 needsCompositing ,它会影响生成多少层的 Layer ,而这些 Layer 又会组成一棵 Layer Tree 。好吧,到这里又多了一个树,实际上这颗树才是所谓真正去给引擎绘制的树。

在这里插入图片描述

我们大概就了解了 RenderObject 的整个绘制流程,并且这个绘制时机我们是去“触发”的,而不是主动调用,并且更新是判断区域的。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-05 20:23:48  更:2021-07-05 20:24:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 14:28:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码