【Flutter -- 布局】流式布局(Flow和Wrap)

在这里插入图片描述

Flow

1. 简介

Flow 是一个实现流式布局算法的控件。流式布局在大前端是很常见的布局方式,但是一般使用 Flow 很少,因为其过于复杂,很多场景下都会去使用 Wrap 。

2. 属性

delegate:影响 Flow 具体布局的 FlowDelegate。

其中 FlowDelegate 包含如下几个方法:

  • getConstraintsForChild: 设置每个 child 的布局约束条件,会覆盖已有的;
  • getSize:设置 Flow 的尺寸;
  • paintChildren:child 的绘制控制代码,可以调整尺寸位置,写起来比较的繁琐;
  • shouldRepaint:是否需要重绘;
  • shouldRelayout:是否需要重新布局。

其中,我们平时使用的时候,一般会使用到 paintChildren 以及 shouldRepaint 两个方法。

3. 使用场景

Flow 在一些定制化的流式布局中,有可用场景,但是一般写起来比较复杂,但胜在灵活性以及其高效。

4. 实例

1. 效果图

在这里插入图片描述

2. 示例代码

import 'package:flutter/material.dart';

void main() {
    
    
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
    
    
  const MyApp({
    
    Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    
    
    return MaterialApp(
        title: 'Welcome to Flutter',

        home: Scaffold(
            appBar: AppBar(
              title: Text('流式布局'),
            ),
            body: Center(
              child: Flow(
                delegate: TestFlowDelegate(margin: EdgeInsets.all(10.0)),
                children: <Widget>[
                  Container(width: 80.0, height:80.0, color: Colors.red,),
                  Container(width: 80.0, height:80.0, color: Colors.green,),
                  Container(width: 80.0, height:80.0, color: Colors.blue,),
                  Container(width: 80.0, height:80.0,  color: Colors.yellow,),
                  Container(width: 80.0, height:80.0, color: Colors.brown,),
                  Container(width: 80.0, height:80.0,  color: Colors.purple,),
                ],
              ),
            )
        )
    );
  }
}

class TestFlowDelegate extends FlowDelegate {
    
    
  EdgeInsets margin;

  TestFlowDelegate({
    
    this.margin = EdgeInsets.zero});

  double width = 0;
  double height = 0;

  @override
  void paintChildren(FlowPaintingContext context) {
    
    
    var x = margin.left;
    var y = margin.top;
    //计算每一个子widget的位置
    for (int i = 0; i < context.childCount; i++) {
    
    
      var w = context.getChildSize(i)!.width + x + margin.right;
      if (w < context.size.width) {
    
    
        context.paintChild(i, transform: Matrix4.translationValues(x, y, 0.0));
        x = w + margin.left;
      } else {
    
    
        x = margin.left;
        y += context.getChildSize(i)!.height + margin.top + margin.bottom;
        //绘制子widget(有优化)
        context.paintChild(i, transform: Matrix4.translationValues(x, y, 0.0));
        x += context.getChildSize(i)!.width + margin.left + margin.right;
      }
    }
  }

  @override
  Size getSize(BoxConstraints constraints) {
    
    
    // 指定Flow的大小,简单起见我们让宽度竟可能大,但高度指定为200,
    // 实际开发中我们需要根据子元素所占用的具体宽高来设置Flow大小
    return Size(double.infinity, 200.0);
  }

  @override
  bool shouldRepaint(FlowDelegate oldDelegate) {
    
    
    return oldDelegate != this;
  }
}

Wrap

1. 简介

流式布局组件,如果内容宽度超出屏幕宽度,会自动折行显示。

2. 属性

  • direction:主轴(mainAxis)的方向,默认为水平。

  • alignment:主轴方向上的对齐方式,默认为start。

  • spacing:主轴方向上的间距。

  • runAlignment:run的对齐方式。run可以理解为新的行或者列,如果是水平方向布局的话,run可以理解为新的一行。

  • runSpacing:run的间距。

  • crossAxisAlignment:交叉轴(crossAxis)方向上的对齐方式。

  • textDirection:文本方向。

  • verticalDirection:定义了children摆放顺序,默认是down,见Flex相关属性介绍。

3. 使用场景

对于一些需要按宽度或者高度,让child自动换行布局的场景,可以使用,但是Wrap可以满足的场景,Flow一定可以实现,只不过会复杂很多,但是相对的会灵活以及高效很多。

4. 实例

1. 效果图

在这里插入图片描述
2. 代码

import 'package:flutter/material.dart';

void main() {
    
    
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
    
    
  const MyApp({
    
    Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    
    
    return MaterialApp(
        title: 'Welcome to Flutter',

        home: Scaffold(
            appBar: AppBar(
              title: Text('流式布局'),
            ),
            body: Center(
              child: Wrap(
                spacing: 8.0,
                runSpacing: 4.0,
                children: <Widget>[
                  Chip(
                    avatar: CircleAvatar(
                        backgroundColor: Colors.green.shade300, child: new Text('AH', style: TextStyle(fontSize: 10.0),)),
                    label: Text('Kevin'),
                  ),

                  Chip(
                    avatar: CircleAvatar(
                        backgroundColor: Colors.green.shade300, child: new Text('ML', style: TextStyle(fontSize: 10.0),)),
                    label: Text('Lafayette'),
                  ),

                  Chip(
                    avatar: CircleAvatar(
                        backgroundColor: Colors.green.shade300, child: new Text('HM', style: TextStyle(fontSize: 10.0),)),
                    label: Text('Aaron'),
                  ),

                  Chip(
                    avatar: CircleAvatar(
                        backgroundColor: Colors.green.shade300, child: new Text('JL', style: TextStyle(fontSize: 10.0),)),
                    label: Text('Laurens'),
                  ),
                ],
              ),
            )
        )
    );
  }
}

猜你喜欢

转载自blog.csdn.net/duoduo_11011/article/details/125886329