文章目录
流式布局
Wrap
Flow
流式布局
流式布局在移动端是非常常见的,比如商品列表,瀑布流、标签页等等。使用Android原生来实现流式布局还是有点麻烦的,甚至需要自定义view或者使用第三方的库。而在Flutter中,官方为我们提供了流式布局的控件,我们可以很方便的实现流式布局。
Wrap
首先来看Wrap,Wrap是一个可以使子控件自动换行的控件,默认的方向是水平的,使用起来非常简单。
首先,对于MainAxisAlignment和CrossAxisAlignment不太熟悉的同学可以先看看下面这篇文章,讲的很详细了。
MainAxisAlignment和CrossAxisAlignment详解
构造方法
Wrap({ Key key, this.direction = Axis.horizontal, //排列方向,默认水平方向排列 this.alignment = WrapAlignment.start, //子控件在主轴上的对齐方式 this.spacing = 0.0, //主轴上子控件中间的间距 this.runAlignment = WrapAlignment.start, //子控件在交叉轴上的对齐方式 this.runSpacing = 0.0, //交叉轴上子控件之间的间距 this.crossAxisAlignment = WrapCrossAlignment.start, //交叉轴上子控件的对齐方式 this.textDirection, //textDirection水平方向上子控件的起始位置 this.verticalDirection = VerticalDirection.down, //垂直方向上子控件的其实位置 List<Widget> children = const <Widget>[], //要显示的子控件集合 }) |
下面我们就来简单的用一用:
import 'package:flutter/material.dart'; /* * 可以让子控件自动换行的控件 * * */ class WrapWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Wrap( spacing: 2, //主轴上子控件的间距 runSpacing: 5, //交叉轴上子控件之间的间距 children: Boxs(), //要显示的子控件集合 ); } /*一个渐变颜色的正方形集合*/ List<Widget> Boxs() => List.generate(10, (index) { return Container( width: 100, height: 100, alignment: Alignment.center, decoration: BoxDecoration( gradient: LinearGradient(colors: [ Colors.orangeAccent, Colors.orange, Colors.deepOrange ]), ), child: Text( "${index}", style: TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, ), ), ); }); } |
Flutter中的流式布局是不是非常简单。
Flow
Flow用起来远比Wrap麻烦,但是它可以实现更加个性化的需求,我们可以通过delegate属性自己设置子控件排列规则。
构造方法
Flow({
Key key,
@required this.delegate, //布局委托,接收一个FlowDelegate类型的值
List<Widget> children = const <Widget>[], //要显示的子控件
})
1
2
3
4
5
我们主要来看看delegate属性,他接收一个FlowDelegate类型的值
FlowDelegate
FlowDelegate是一个抽象类,我们一般会重写paintChildren方法,在该方法中,我们可以来控制子控件的摆放。
import 'package:flutter/material.dart'; /* * 流式布局 * 自定义FlowDelegate * */ double boxSize = 80.0; class FlowWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Flow( delegate: MyFlowDelegate(), children: List.generate(10, (index) { return Box(index); }), ); } /*一个带渐变颜色的正方形*/ Widget Box(index) => Container( width: boxSize, height: boxSize, alignment: Alignment.center, decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.orangeAccent, Colors.orange, Colors.deepOrange]), ), child: Text( index.toString(), style: TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, ), ), ); } class MyFlowDelegate extends FlowDelegate { @override void paintChildren(FlowPaintingContext context) { /*屏幕宽度*/ var screenW = context.size.width; double padding = 5; //间距 double offsetX = padding; //x坐标 double offsetY = padding; //y坐标 for (int i = 0; i < context.childCount; i++) { /*如果当前x左边加上子控件宽度小于屏幕宽度 则继续绘制 否则换行*/ if (offsetX + boxSize < screenW) { /*绘制子控件*/ context.paintChild(i, transform: Matrix4.translationValues(offsetX, offsetY, 0)); /*更改x坐标*/ offsetX = offsetX + boxSize + padding; } else { /*将x坐标重置为margin*/ offsetX = padding; /*计算y坐标的值*/ offsetY = offsetY + boxSize + padding; /*绘制子控件*/ context.paintChild(i, transform: Matrix4.translationValues(offsetX, offsetY, 0)); } } } @override bool shouldRepaint(FlowDelegate oldDelegate) { return true; } } ———————————————— |
在正常情况下,能用wrap就用wrap,实现其来比较简单,如果是比较个性化的排列规则,可以使用Flow来实现。
好了,Flutter流式布局大概就是这样。
https://blog.csdn.net/yuzhiqiang_1993/article/details/88378021