Flutter知识梳理 布局篇《三》
自定义多子布局 CustomMultiChildLayout
CustomMultiChildLayout
中也是通过代理类
进行自定义布局逻辑的,类型为 MultiChildLayoutDelegate
。
思路 : 如果想要使用CustomMultiChildLayout来自定义多子组件,要通过使用其代理类来实现,先看看代理类怎么使用的,再随便画画,多子布局。
MultiChildLayoutDelegate 使用
-
使用
layoutChild
方法为每个子节点设置布局约束。 -
使用
positionChild
方法为每个子节点设置水平偏移位置。 -
在
performLayout
中通过layoutChild
对子级进行布局,通过positionChild
对子级进行定位。 -
hasChild
方法
方法用于判断给定的值是否代表一个子节点。它的作用是帮助布局代理识别哪些是合法的子节点值。
如果你使用
Key
或其他唯一标识符来标识子节点,你需要重写hasChild
方法,根据传入的值判断是否存在对应的子节点.
在源码组件NavigationToolbar
中就有使用 hasChild
来判断
在 _ToolbarLayout
的 performLayout
方法中 使用 hasChild
来判断是否传入指定的子节点。
没有为子节点提供显式的标识符,也可以直接将子节点的索引作为标识符
设计
代码实现
代理类的实现
class StaggeredGridLayoutDelegate extends MultiChildLayoutDelegate {
@override
void performLayout(Size size) {
double itemWidth = size.width / 4; // 每行两个组件,间距两个
double itemHeight = itemWidth; // 正方形组件
late double xOffset;
for (int i = 0; i < 8; i++) {
if (hasChild('child$i')) {
int row = i ~/ 2; //一共几行
if (row % 2 == 0) {
// 偶数行 布局从0开始
xOffset = i % 2 == 0 ? 0 : itemWidth * 2;
} else {
//奇数行布局从itemWidth开始
xOffset = i % 2 == 0 ? itemWidth : itemWidth * 3;
}
double yOffset = row * itemHeight;
layoutChild('child$i', BoxConstraints.tight(Size(itemWidth, itemHeight))); //子组件宽高
positionChild('child$i', Offset(xOffset, yOffset)); //子组件的定位
}
}
}
@override
bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) => false;
}
布局
class CustomMulti extends StatefulWidget {
const CustomMulti({Key? key}) : super(key: key);
@override
State<CustomMulti> createState() => _CustomMultiState();
}
class _CustomMultiState extends State<CustomMulti> {
@override
Widget build(BuildContext context) {
return CustomMultiChildLayout(
delegate: StaggeredGridLayoutDelegate(),
children: List.generate(8, (index) {
return LayoutId(
id: 'child$index',
child: Container(
color: Colors.blue,
),
);
}),
);
}
}
使用
Container(
width:200,
height: 200,
color: const Color(0xff24B718),
child: CustomMulti(),
),
效果
转载自:https://juejin.cn/post/7371370680514822182