最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Flutter学习:什么是Container以及布局约束的实现

    正文概述 掘金(落魄程序员在线炒饭)   2021-06-02   797

    前言

    在Flutter开发中,Container作为一个容器类的Widget,有点类似HTML的div,在项目中也是高频使用;那在使用过程中,你是否有过下面的这些疑问:

    1. Container是什么,它如何实现的?
    2. Container的大小约束规则是什么?下面几种情况你知道为什么吗?

    Flutter学习:什么是Container以及布局约束的实现

    Container介绍

    首先我们来看一下Contaienr是什么: Flutter学习:什么是Container以及布局约束的实现 可以看到,通过上面可以知道,Container是继承自StatelessWidget的widget,有丰富的属性配置,通过这些属性,我们可以设置前景,背景,颜色,内外边距,裁剪方式,对齐方式等。而且由于Container是继承自StatelessWidget,所以它并不能构建renderObject,不能直接参与绘制,所以看一下它的build()函数的实现:

    @override
      Widget build(BuildContext context) {
        Widget current = child;
        if (child == null && (constraints == null || !constraints.isTight)) {
          current = LimitedBox(
            maxWidth: 0.0,
            maxHeight: 0.0,
            child: ConstrainedBox(constraints: const BoxConstraints.expand()),
          );
        }
        if (alignment != null)
          current = Align(alignment: alignment, child: current);
        final EdgeInsetsGeometry effectivePadding = _paddingIncludingDecoration;
        if (effectivePadding != null)
          current = Padding(padding: effectivePadding, child: current);
        if (color != null)
          current = ColoredBox(color: color, child: current);
        if (clipBehavior != Clip.none) {
          assert(decoration != null);
          current = ClipPath(
            clipper: _DecorationClipper(
              textDirection: Directionality.of(context),
              decoration: decoration
            ),
            clipBehavior: clipBehavior,
            child: current,
          );
        }
        if (decoration != null)
          current = DecoratedBox(decoration: decoration, child: current);
        if (foregroundDecoration != null) {
          current = DecoratedBox(
            decoration: foregroundDecoration,
            position: DecorationPosition.foreground,
            child: current,
          );
        }
        if (constraints != null)
          current = ConstrainedBox(constraints: constraints, child: current);
        if (margin != null)
          current = Padding(padding: margin, child: current);
        if (transform != null)
          current = Transform(transform: transform, child: current);
        return current;
      }
    

    通过build()函数可以知道,Container只是对不同的renderObjectWidget的组合封装。这简化了我们布局时的widget嵌套层数;其次,注意这里各种widgets的组合的先后顺序,flutter的“盒模型”没有内外边距的概念,边距的实现是通过嵌套一个“盒子”实现的,我们能看到边距的效果,就是因为这里的顺序,是先嵌套了边距widget,这个widget的大小是child的大小加上我们设置的"padding"。关于大小约束在后面再具体聊。

    Flutter学习:什么是Container以及布局约束的实现

    大小和约束的流程

    在学习大小约束之前,我们需要知道renderObject的布局计算流程。我们定位到RenderObject类中,定位到函数:

    abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin implements HitTestTarget {
      void layout(Constraints constraints, { bool parentUsesSize = false }) {
        if (!kReleaseMode && debugProfileLayoutsEnabled)
          Timeline.startSync('$runtimeType',  arguments: timelineArgumentsIndicatingLandmarkEvent);
        ...
        RenderObject? relayoutBoundary;
        if (!parentUsesSize || sizedByParent || constraints.isTight || parent is! RenderObject) {
          relayoutBoundary = this;
        } else {
          relayoutBoundary = (parent as RenderObject)._relayoutBoundary;
        }
        ...
        if (!_needsLayout && constraints == _constraints && relayoutBoundary == _relayoutBoundary) {
          ...
          if (!kReleaseMode && debugProfileLayoutsEnabled)
            Timeline.finishSync();
          return;
        }
        _constraints = constraints;
        ...
        if (sizedByParent) {
          ...
          try {
            performResize();
            ...
          } catch (e, stack) {
            ...
          }
          ...
        }
        ...
        try {
          performLayout();
          ...
        } catch (e, stack) {
          ...
        }
        ...
        _needsLayout = false;
        markNeedsPaint();
        if (!kReleaseMode && debugProfileLayoutsEnabled)
          Timeline.finishSync();
      }
      
      
      @protected
      void performResize();
      
      @protected
      void performLayout();
      
      void paint(PaintingContext context, Offset offset) { }
      
    }
    
    

    找一个layout的调用:

    Flutter学习:什么是Container以及布局约束的实现

    Flutter学习:什么是Container以及布局约束的实现 好了,我们来分析一下:layout函数的入参是一个约束,可以从外部获取约束,然后再调用performResizeperformLayout,这里官方要求子类不能重写layout,而是直接重写performResizeperformLayout;主要的作用是:把自己的约束传给子类;从子类获取大小;继续绘制子类,最后通过类的paint函数进行绘制。整个过程递归,就完成了各个renderObject的大小和约束的计算并绘制。

    约束规则

    偷个懒直接看Flutter官网的介绍:

    Flutter学习:什么是Container以及布局约束的实现


    起源地下载网 » Flutter学习:什么是Container以及布局约束的实现

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元