Flutter 系统是如何实现ExpansionPanelList的-LMLPHP

在了解ExpansionPanelList实现前,先来了解下MergeableMaterial,它展示多个MergeableMaterialItem组件,当子组件发生变化时,以动画的方式打开或者关闭子组件,MergeableMaterial的父控件需要在主轴方向是一个没有限制的控件,比如SingleChildScrollView、Row、Column等。

基本用法如下:

SingleChildScrollView(
  child: MergeableMaterial(
    children: [
      MaterialSlice(
          key: ValueKey(1),
          child: Container(
            height: 45,
            color: Colors.primaries[1 % Colors.primaries.length],
          )),
      MaterialGap(key: ValueKey(2)),
      MaterialSlice(
          key: ValueKey(3),
          child: Container(
            height: 45,
            color: Colors.primaries[1 % Colors.primaries.length],
          )),
      MaterialGap(key: ValueKey(4)),
      MaterialSlice(
          key: ValueKey(5),
          child: Container(
            height: 45,
            color: Colors.primaries[1 % Colors.primaries.length],
          )),
    ],
  ),
)

效果如下:

Flutter 系统是如何实现ExpansionPanelList的-LMLPHP

MergeableMaterial的子控件只能是MaterialSlice和MaterialGap,MaterialSlice是带子控件的控件,显示实际内容,MaterialGap用于分割,只能放在MaterialSlice中间。

静态情况下,看不出具体的效果,动态改变子组件用法如下:

List<MergeableMaterialItem> items = [];
List.generate(_count, (index) {
  items.add(MaterialSlice(
      key: ValueKey(index * 2),
      child: Container(
        height: 45,
        color: Colors.primaries[index % Colors.primaries.length],
      )));
});

return SingleChildScrollView(
  child: MergeableMaterial(
    children: items,
  ),
)

效果如下:

Flutter 系统是如何实现ExpansionPanelList的-LMLPHP

主要看增加/删除子组件时的动画效果。

增加分割线和阴影:

MergeableMaterial(
  hasDividers: true,
  elevation: 24,
  children: items,
)

效果如下:

Flutter 系统是如何实现ExpansionPanelList的-LMLPHP

阴影值不能随便设置,只能设置如下值:1, 2, 3, 4, 6, 8, 9, 12, 16, 24

此控件可以实现什么样的效果呢?看下面效果:

Flutter 系统是如何实现ExpansionPanelList的-LMLPHP

实现代码:

bool _expand = false;

@override
Widget build(BuildContext context) {
  return Column(
    children: <Widget>[
      Container(
        height: 45,
        color: Colors.green.withOpacity(.3),
        alignment: Alignment.centerRight,
        child: IconButton(
          icon: Icon(Icons.arrow_drop_down),
          onPressed: () {
            setState(() {
              _expand = !_expand;
            });
          },
        ),
      ),
      _expand
          ? MergeableMaterial(
              hasDividers: true,
              elevation: 24,
              children: [
                MaterialSlice(
                    key: ValueKey(1),
                    child: Container(
                      height: 200,
                      color: Colors.green.withOpacity(.3),
                    ))
              ],
            )
          : Container(),
      Container(
        height: 45,
        color: Colors.red.withOpacity(.3),
      ),
    ],
  );
}

看到这个效果是否想到了ExpansionPanelList呢?系统控件ExpansionPanelList就是使用此控件实现的。

交流

老孟Flutter博客地址(近200个控件用法):http://laomengit.com

欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:

Flutter 系统是如何实现ExpansionPanelList的-LMLPHPFlutter 系统是如何实现ExpansionPanelList的-LMLPHP
09-04 03:33