美文网首页Flutter教学
Flutter(64):Layout组件之Flow

Flutter(64):Layout组件之Flow

作者: starryxp | 来源:发表于2020-10-22 15:52 被阅读0次

    Flutter教学目录持续更新中

    Github源代码持续更新中

    1.Flow介绍

    一个实现流式布局算法的widget
    用法跟CustomSingleChildLayout很像,但是比CustomSingleChildLayout更加强大

    2.Flow属性

    • delegate:FlowDelegate
    • children = const <Widget>[]:

    3.FlowDelegate

    • void paintChildren(FlowPaintingContext context):这个方法是用来绘制子组件的
    • Size getSize(BoxConstraints constraints):获取父容器约束条件确定Flow大小
    • bool shouldRepaint(covariant FlowDelegate oldDelegate):是否需要重绘
    • BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints):确定child的约束
    • bool shouldRelayout(FlowDelegate oldDelegate):是否需要relayout

    4.FlowPaintingContext

    • size:可以用来绘制的空间大小
    • childCount:子组件数量
    • getChildSize(int i):获取子组件
    • paintChild(int i, { Matrix4 transform, double opacity = 1.0 }):绘制子组件,默认从左上角开始
      可以看到这里绘制是用Matrix4绘制的,那么他将可以实现移动,缩放,旋转,扭曲等一系列的矩阵变换。Matrix4这个在之前介绍过:Flutter(59):Layout组件之Transform

    5.使用

      _myChildren() {
        return [
          Container(
            color: Colors.cyan,
            width: 80,
            height: 50,
          ),
          Container(
            color: Colors.red,
            width: 150,
            height: 50,
          ),
          Container(
            color: Colors.yellow,
            width: 200,
            height: 50,
          ),
          Container(
            color: Colors.blue,
            width: 300,
            height: 50,
          ),
          Container(
            color: Colors.grey,
            width: 110,
            height: 50,
          ),
          Container(
            color: Colors.green,
            width: 180,
            height: 50,
          ),
        ];
      }
    
          body: Flow(
            delegate: _MyFlowDelegate(),
            children: _myChildren(),
          ),
    
    class _MyFlowDelegate extends FlowDelegate {
      @override
      void paintChildren(FlowPaintingContext context) {
        var dx = 0.0;
        var dy = 0.0;
        for (int i = 0; i < context.childCount; i++) {
          if (dx + context.getChildSize(i).width < context.size.width) {
          } else {
            dx = 0;
            dy += context.getChildSize(i).height;
          }
          context.paintChild(
            i,
            transform: Matrix4.compose(
              Vector.Vector3(dx, dy, 0),
              Vector.Quaternion(0, 0, 0, 0),
              Vector.Vector3(1, 1, 1),
            ),
          );
          dx += context.getChildSize(i).width;
        }
      }
    
      @override
      Size getSize(BoxConstraints constraints) {
        //获取父容器约束条件确定Flow大小
        print('getSize constraints = $constraints');
        return super.getSize(constraints);
      }
    
      @override
      bool shouldRepaint(covariant FlowDelegate oldDelegate) {
        return false;
      }
    
      @override
      BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints) {
        //确定child的约束,用于确定child的大小
        print('getConstraintsForChild constraints = $constraints ');
        return super.getConstraintsForChild(i, constraints);
      }
    
      @override
      bool shouldRelayout(FlowDelegate oldDelegate) {
        //是否需要relayout
        return false;
      }
    }
    
    image.png

    Flow支持按你想要的方式去实现布局,例如这里判断每行剩余空间是否能放下子控件,放不下就换行绘制。当然了这里写的比较简单,只是给大家提供一下简单的演示。

    我们之前也看到了,FlowPaintingContext绘制是使用的Matrix4,那么也就是说我们可以通过一个变量来改变Matrix4的属性达到让Flow子控件运动起来的效果,下面我们来试一下:

    AnimationController _animationController;
      double scale = 0;
    
      @override
      void initState() {
        _animationController = AnimationController(
            duration: Duration(milliseconds: 3000), vsync: this);
        _animationController.addListener(() {
          setState(() {
            scale = _animationController.value * 2;
            print("scale = $scale");
          });
        });
        _animationController.forward();
        super.initState();
      }
    
      @override
      void dispose() {
        _animationController.dispose();
        super.dispose();
      }
    
    class _MyAnimFlowDelegate extends FlowDelegate {
      _MyAnimFlowDelegate(this.scale);
    
      final double scale;
    
      @override
      void paintChildren(FlowPaintingContext context) {
        for (int i = 0; i < context.childCount; i++) {
          context.paintChild(
            i,
            transform: Matrix4.compose(
              Vector.Vector3(0, 0, 0),
              Vector.Quaternion(0, 0, 0, 0),
              Vector.Vector3(scale, scale, 1),
            ),
          );
        }
      }
    
      @override
      Size getSize(BoxConstraints constraints) {
        //获取父容器约束条件确定Flow大小
        print('getSize constraints = $constraints');
        return super.getSize(constraints);
      }
    
      @override
      bool shouldRepaint(covariant FlowDelegate oldDelegate) {
        return true;
      }
    
      @override
      BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints) {
        //确定child的约束,用于确定child的大小
        print('getConstraintsForChild constraints = $constraints ');
        return super.getConstraintsForChild(i, constraints);
      }
    
      @override
      bool shouldRelayout(FlowDelegate oldDelegate) {
        //是否需要relayout
        return false;
      }
    }
    
          body: Flow(
            delegate: _MyAnimFlowDelegate(scale),
            children: [
              Container(
                width: 50,
                height: 50,
                decoration:
                    BoxDecoration(color: Colors.red, shape: BoxShape.circle),
              ),
              InkWell(
                onTap: () {
                  _animationController.reset();
                  _animationController.forward();
                },
              )
            ],
          ),
    

    这里实现的效果很简单,就是使用一个AnimationController控制器,让一个红色圆实现放大效果,InkWell是添加一个点击事件。由于本教程对动画还没有讲解到,这里就不再做比较难的特效了,目的只是为了演示Flow的强大能力。

    image.png

    下一节:Layout组件之FlowTable

    Flutter(65):Layout组件之FlowTable

    Flutter教学目录持续更新中

    Github源代码持续更新中

    相关文章

      网友评论

        本文标题:Flutter(64):Layout组件之Flow

        本文链接:https://www.haomeiwen.com/subject/ltxymktx.html