Code前端首页关于Code前端联系我们

Flutter开发实践九:深图原理

terry 2年前 (2023-09-23) 阅读数 66 #移动小程序

关系我知道widget元素、对象❓❓❓我也知道小部件。布局逻辑最终将转换所有 小部件 Render 对象,这些是我们要创建的图像堆栈。

所以在Flutter中,最后一页LayoutPaint等都出现在object♿u子类的❓小部件和Render Object中也是Flutter 最大的跨平台功能之一:所有控件都是独立于平台的。用通俗易懂的话说:Flutter 只需要系统提供的“画布”。然后,开发人员通过小部件生成 Render 对象 ,并通过引擎将其“直接”绘制到屏幕上。

ps 从现在开始这篇文章会有点长,所以可能需要你一些耐心。

1。绘图过程

我们知道widget最终会转换为Render对象,所以为了理解绘图,我们看一下❿Pu对象P 的方法。

如下图所示,Render对象的所有子类都必须实现paint方法,并且该方法不是由用户直接调用的。如果需要更新绘图,可以通过 markNeddsPaint 方法开始绘制界面。Flutter开发实战九:深入绘制原理

然后按照“国际化流程”,计算好位置、大小、布局等后,调用最终的paint方法,该方法有两个参数:PaintingContext和Offset,这是完成绘图的关键,所以相信大家现在一定有一个疑问:

  • PaintingContext是什么?什么是
  • 偏移

通过快速检查源代码,我们首先了解:

  • paintingcontext密钥是一个可以绘制-Text的地方。包含
。有 CanvasPaintingContext, 仅受

♹@Flutter开发实战九:深入绘制原理

PaintingContext.repaintCompositedChild 保护,当 时创建 和 pushLayer自动地。

  • Offset 在函数paint中,主要给出当前控件在屏幕上的相对偏移值,给出绘制时确定图形的坐标。
  • Flutter开发实战九:深入绘制原理

    OK,继续往下走,那么既然PaintingContext称为上下文,那么它肯定有上下文关系,那么它是在哪里创建的呢?

    调试源码,可以看到Appid被App启动时,项目启动了WidgetsFlutterBinding,在上一篇文章我们知道❓ flutterBinding 是一种“胶水类型”,它从 mixin 启动 RendererBinding,如下所示,以创建根文本 Pain♿kon❙。 。 Flutter开发实战九:深入绘制原理

    好吧,但是位移?如下图所示,Offset的传递是通过将父子控件的偏移量相加,然后按级别组合绘图坐标来完成的。

    简单地说,穿过PaintingContext偏移。布局之后,我们可以在屏幕上正确的位置绘制必要的图像。 Flutter开发实战九:深入绘制原理

    1。测试图

    这里我们先做一个有趣的测试。

    现在我们通过容器在屏幕上绑定高度为60的绿色容器,如下图所示。暂时忽略容器中的按钮 Slider。我们在图上画了。 100 为什么这么小?

    其实,由于正常情况下Flutter会绘制容器,所以AppBar已经帮我们计算了高度偏差,只不过这里我们使用了statusbar❓vas❓。 是直接且原始的 drawRect。画的小红框,的左边和上边的起点都是0,是从状态栏计算出来的。 Flutter开发实战九:深入绘制原理

    如果我们调整位置呢?将起点顶部调整为300,就会出现如下图的效果:Nani?红色的小方块是实际绘制出来的,很明显容器只有绿色的大小。 Flutter开发实战九:深入绘制原理

    其实问题出在绘画语境。它有一个参数 estimatedBoundsestimatedBounds 通常在创建过程中传递。 child.paintBounds 设置了,但是estimatedBounds还有如下描述: 原来它也可以画图。

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

    所以这里可以总结一下流行的方式。在Flutter中,整个屏幕就是一个画布,我们将位置设置为不同的Offset和❓,然后通过PaintingContextcanvas进行绘制。目标是整个屏幕区域,整个屏幕就是一帧。每次更改都会重新绘制。

    2。 ReaintBoundary

    当然,每次重新绘制时,它并不会完全重新绘制。事实上,是有一些规定的。

    还记得之前的markNeedsPaint方法吗?我们先从函数markNeedsPaint()开始,总结一下它的整体流程如下图。可以看到,当请求VisualUpdate绘制界面时,markNeedsPaint触发引擎更新。 Flutter开发实战九:深入绘制原理

    那么我们看一下源码。如源码所示,当调用markNeedsPaint()时,Render Object会根据Flutter开发实战九:深入绘制原理

    res的配对来查找上面的父节点,最终决定是否真实是否从这里开始重画。换句话说, 指定要更新的区域。

    所以实际的流程应该是:通过isRepaintBoundary设置更新区域,并通过方法运行更新收集。 Flutter开发实战九:深入绘制原理

    而且从源码中可以看到,函数isRepaintBoundary只有get和de,所以可以被子类覆盖♿♿class表示是否用于border绘画,例如Render ProxyBoxRender View❿❓❓ Render View。 objectRenderisRepaintBoundary都是真的。

    因此,如果该区域经常重绘并且不影响父控件,您实际上可以将覆盖isRepaintBoundary设置为true。

    3。 Layer

    正如我们上面所知,如果isRepaintBoundary为true,那么该区域是一个可重绘的绘图区域,并且在创建该区域时实际上创建了一个新的绘图区域。 .不同下的

    Render对象可以独立工作,例如❓♹❓Render用于对象,它被使用在定位图中。Flutter开发实战九:深入绘制原理

    同时也引出了一个结论:不是每个Render物体都有B层,因为它受到Flutter开发实战九:深入绘制原理

    ary的影响。

    其次,文档Render Object有一个名为needsCompositing的属性,它会影响♷♷层的生成。 d 并且这些形成层树。嗯,这是另一棵树。事实上,这棵树就是所谓的树,实际上是为引擎绘制的。 Flutter开发实战九:深入绘制原理

    目前,我们大致了解了Render对象的整个绘制过程,并且我们“触发”绘制的时机,而不是主动调用它,更新是基于决策区域的。 。 嗯~味道有点像React!

    2.滑块控件绘图实现

    前面讲了这么多绘图流程,现在我们就从Slider的源码开始,看一下绘图控件的设计与实现。 Flutter开发实战九:深入绘制原理

    整个Slider的实现可以说是非常Flutter。总体结构如下图所示。

    _Render滑块手势和和,绘图 是动画❀。由slidrthemedata提供滑动主题

    巧合的是,SliderTheme本身就是一个继承的Widget。看过前面章节的同学应该知道,inhedwidget一般是用来分享状态的,所以如果你需要自定义Slider,可以通过SliderThemeNest来完成然后可以选择通过SliderThemeData自定义所需的模块。Flutter开发实战九:深入绘制原理

    并且如下图所示,在_Render滑块中注册时,显示器上的手势和动画会触发markNeedsPaint方法。这就是您的触摸对屏幕产生反应的原因。 。 Flutter开发实战九:深入绘制原理

    同时可以看到_Slider Render中的参数被重写在方法get和中。 设置方法。 markNeedSpaint()或调用_UpDateLabelPainter间接调用markNeedSLayoutFlutter开发实战九:深入绘制原理

    至于绘制Slider不同形状,都是Canvas标准

    Flutter开发实战九:深入绘制原理

    drawRect

    ,翻译. drawPath

    和其他熟悉的动作。

    作者:连毛德小果
    链接:https://juejin.im/post/5ca0e0aff265da309728659a
    版权所有❿版权所有来源:♓对于商业转载请联系作者授权。非商业转载请注明出处。

    版权声明

    本文仅代表作者观点,不代表Code前端网立场。
    本文系作者Code前端网发表,如需转载,请注明页面地址。

    发表评论:

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

    热门