Flutter开发实践九:深图原理
关系我知道widget
、元素
、对象❓❓❓我也知道小部件。布局逻辑最终将转换所有 小部件
Render 对象
,这些是我们要创建的图像堆栈。
所以在Flutter中,最后一页 ps 从现在开始这篇文章会有点长,所以可能需要你一些耐心。 我们知道 如下图所示, 然后按照“国际化流程”,计算好位置、大小、布局等后,调用最终的 通过快速检查源代码,我们首先了解:Layout
、Paint
等都出现在object♿u子类的❓小部件和Render Object中也是Flutter 最大的跨平台功能之一:所有控件都是独立于平台的。用通俗易懂的话说:Flutter 只需要系统提供的“画布”。然后,开发人员通过小部件生成
♹@Render 对象
,并通过引擎将其“直接”绘制到屏幕上。 1。绘图过程
widget
最终会转换为Render对象
,所以为了理解绘图,我们看一下❿Pu对象P 的方法。
Render对象
的所有子类都必须实现paint
方法,并且该方法不是由用户直接调用的。如果需要更新绘图,可以通过 markNeddsPaint
方法开始绘制界面。paint
方法,该方法有两个参数:PaintingContext和
。有 Offset
,这是完成绘图的关键,所以相信大家现在一定有一个疑问:PaintingContext
是什么?什么是偏移
? paintingcontext
密钥是一个可以绘制-Text的地方。包含Canvas
和 PaintingContext
, 仅受
PaintingContext.repaintCompositedChild 保护,当 时创建 和 pushLayer
自动地。
Offset
在函数paint
中,主要给出当前控件在屏幕上的相对偏移值,给出绘制时确定图形的坐标。 OK,继续往下走,那么既然PaintingContext
称为上下文,那么它肯定有上下文关系,那么它是在哪里创建的呢?
调试源码,可以看到Appid被App启动时,项目启动了
我们知道❓ flutterBinding 是一种“胶水类型”,它从 mixin 启动 WidgetsFlutterBinding
,在上一篇文章RendererBinding
,如下所示,以创建根文本 Pain♿kon❙。 。
好吧,但是位移
?如下图所示,Offset
的传递是通过将父子控件的偏移量相加,然后按级别组合绘图坐标来完成的。
简单地说,穿过PaintingContext
和偏移
。布局之后,我们可以在屏幕上正确的位置绘制必要的图像。
1。测试图
这里我们先做一个有趣的测试。
现在我们通过容器
在屏幕上绑定高度为60的绿色容器,如下图所示。暂时忽略容器中的按钮 Slider
。我们在图上画了。 100 为什么这么小?
其实,由于正常情况下Flutter会绘制容器
,所以AppBar
已经帮我们计算了高度偏差,只不过这里我们使用了statusbar❓vas❓。 是直接且原始的 drawRect
。画的小红框,的左边和上边的起点都是0,是从状态栏计算出来的。
如果我们调整位置呢?将起点顶部调整为300,就会出现如下图的效果:Nani?红色的小方块是实际绘制出来的,很明显容器
只有绿色的大小。
其实问题出在绘画语境
。它有一个参数 estimatedBounds
和 estimatedBounds
通常在创建过程中传递。 child.paintBounds
设置了,但是estimatedBounds
还有如下描述: 原来它也可以画图。
The canvas will allow painting outside these bounds.
The [estimatedBounds] rectangle is in the [canvas] coordinate system.
复制代码
所以这里可以总结一下流行的方式。在Flutter中,整个屏幕就是一个画布,我们将位置设置为不同的Offset
和❓,然后通过PaintingContext
canvas进行绘制。目标是整个屏幕区域,整个屏幕就是一帧。每次更改都会重新绘制。
2。 ReaintBoundary
当然,每次重新绘制时,它并不会完全重新绘制。事实上,是有一些规定的。
还记得之前的markNeedsPaint
方法吗?我们先从函数markNeedsPaint()
开始,总结一下它的整体流程如下图。可以看到,当请求VisualUpdate
绘制界面时,markNeedsPaint
触发引擎更新。
那么我们看一下源码。如源码所示,当调用markNeedsPaint()
时,Render Object
会根据
res的配对来查找上面的父节点,最终决定是否真实是否从这里开始重画。换句话说, 指定要更新的区域。
所以实际的流程应该是:通过isRepaintBoundary
设置更新区域,并通过方法运行更新收集。
而且从源码中可以看到,函数 因此,如果该区域经常重绘并且不影响父控件,您实际上可以将覆盖 正如我们上面所知,如果 同时也引出了一个结论:不是每个 ary的影响。 其次,文档 目前,我们大致了解了 前面讲了这么多绘图流程,现在我们就从 整个 巧合的是, 并且如下图所示,在 同时可以看到 至于绘制 drawRectisRepaintBoundary
只有get
和de,所以可以被子类覆盖♿♿class表示是否用于border绘画,例如Render ProxyBox
、Render View
、❿❓❓ Render View。 objectRender
和其他熟悉的动作。 isRepaintBoundary
都是真的。 isRepaintBoundary
设置为true。 3。 Layer
isRepaintBoundary
为true,那么该区域是一个可重绘的绘图区域,并且在创建该区域时实际上创建了一个新的绘图区域。 层
.不同层
下的Render对象
可以独立工作,例如❓♹❓Render用于对象
,它被使用在定位图中。Render物体
都有B层,因为它受到
Render Object
有一个名为needsCompositing
的属性,它会影响♷♷层的生成。 d 并且这些层
形成层树。嗯,这是另一棵树。事实上,这棵树就是所谓的树,实际上是为引擎绘制的。 Render对象
的整个绘制过程,并且我们“触发”绘制的时机,而不是主动调用它,更新是基于决策区域的。 。 嗯~味道有点像React! 2.滑块控件绘图实现
Slider
的源码开始,看一下绘图控件的设计与实现。 Slider
的实现可以说是非常Flutter
。总体结构如下图所示。 _Render滑块
,手势和和,绘图 是动画❀。由slidrthemedata提供
,滑动主题
。 SliderTheme
本身就是一个继承的Widget
。看过前面章节的同学应该知道,inhedwidget
一般是用来分享状态的,所以如果你需要自定义Slider
,可以通过SliderTheme
Nest来完成然后可以选择通过SliderThemeData
自定义所需的模块。_Render滑块中注册时,显示器上的手势和动画会触发
markNeedsPaint
方法。这就是您的触摸对屏幕产生反应的原因。 。 _Slider Render
中的参数被重写在方法get和
中。 设置方法。
有markNeedSpaint()
或调用_UpDateLabelPainter
间接调用markNeedSLayout
。 Slider
不同形状,都是Canvas
标准翻译
. drawPath
作者:连毛德小果
链接:https://juejin.im/post/5ca0e0aff265da309728659a
版权所有❿版权所有来源:♓对于商业转载请联系作者授权。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。