likes
comments
collection
share

Flutter知识梳理 布局篇《三》

作者站长头像
站长
· 阅读数 34

自定义多子布局 CustomMultiChildLayout

CustomMultiChildLayout 中也是通过代理类进行自定义布局逻辑的,类型为 MultiChildLayoutDelegate 。

思路 : 如果想要使用CustomMultiChildLayout来自定义多子组件,要通过使用其代理类来实现,先看看代理类怎么使用的,再随便画画,多子布局。

MultiChildLayoutDelegate 使用

  • 使用 layoutChild 方法为每个子节点设置布局约束。

  • 使用 positionChild 方法为每个子节点设置水平偏移位置。

  • 在 performLayout 中通过 layoutChild 对子级进行布局,通过 positionChild 对子级进行定位。

  • hasChild 方法

方法用于判断给定的值是否代表一个子节点。它的作用是帮助布局代理识别哪些是合法的子节点值。

如果你使用 Key 或其他唯一标识符来标识子节点,你需要重写 hasChild 方法,根据传入的值判断是否存在对应的子节点.

在源码组件NavigationToolbar中就有使用 hasChild 来判断

Flutter知识梳理 布局篇《三》

_ToolbarLayoutperformLayout方法中 使用 hasChild 来判断是否传入指定的子节点。

Flutter知识梳理 布局篇《三》

没有为子节点提供显式的标识符,也可以直接将子节点的索引作为标识符

设计

Flutter知识梳理 布局篇《三》

代码实现

代理类的实现

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(),
),

效果

Flutter知识梳理 布局篇《三》

转载自:https://juejin.cn/post/7371370680514822182
评论
请登录