美文网首页
Flutter 组件之 ExpansionPanel、Expan

Flutter 组件之 ExpansionPanel、Expan

作者: maskerII | 来源:发表于2022-05-19 21:02 被阅读0次

    ExpansionPanel、ExpansionPanelRadio 是一种常见的折叠框。
    ExpansionPanelList 是承载折叠框的一个父类控件。

    1. ExpansionPanel

    ExpansionPanel 定义

      ExpansionPanel({
        required this.headerBuilder,
        required this.body,
        this.isExpanded = false,
        this.canTapOnHeader = false,
        this.backgroundColor,
      })
    

    ExpansionPanel 属性

    ExpansionPanel 属性 介绍
    headerBuilder @required,Header Widget 构造方法
    body @required,展开部分 Widget
    isExpanded 是否展开,默认为 false
    canTapOnHeader 点击 header 是否可以展开收起,false
    backgroundColor 背景色

    2. ExpansionPanelRadio

    ExpansionPanelRadio 定义

      ExpansionPanelRadio({
        required this.value,
        required ExpansionPanelHeaderBuilder headerBuilder,
        required Widget body,
        bool canTapOnHeader = false,
        Color? backgroundColor,
      })
    

    ExpansionPanelRadio属性

    ExpansionPanelRadio属性 介绍
    value @required 唯一标识
    headerBuilder @required Header Widget 构造方法
    body @required,展开部分 Widget
    canTapOnHeader 是否可以点击 header 用来展开收起,false
    backgroundColor 背景色

    3. ExpansionPanelList

    3.1 ExpansionPanelList 默认构造函数

    ExpansionPanelList 定义

      const ExpansionPanelList({
        Key? key,
        this.children = const <ExpansionPanel>[],
        this.expansionCallback,
        this.animationDuration = kThemeAnimationDuration,
        this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
        this.dividerColor,
        this.elevation = 2,
      }) 
    

    ExpansionPanelList属性

    ExpansionPanelList属性 介绍
    children 子控件数组,List<ExpansionPanel>
    expansionCallback 展开收起回调函数,(index, isExpand){},返回当前下标以及是否折叠
    animationDuration 动画时间,默认为 kThemeAnimationDuration
    expandedHeaderPadding 展开后 Header 的 padding,默认为 _kPanelHeaderExpandedDefaultPadding
    dividerColor 分割线颜色
    elevation 阴影大小 不可以随意设置,具体看kElevationToShadow

    3.2 ExpansionPanelList.radio

    ExpansionPanelList.radio 定义

      const ExpansionPanelList.radio({
        Key? key,
        this.children = const <ExpansionPanelRadio>[],
        this.expansionCallback,
        this.animationDuration = kThemeAnimationDuration,
        this.initialOpenPanelValue,
        this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
        this.dividerColor,
        this.elevation = 2,
      })
    

    ExpansionPanelList.radio属性

    ExpansionPanelList.radio属性 介绍
    children 子控件数组,List< ExpansionPanelRadio >
    expansionCallback 展开收起回调函数,(index, isExpand){},返回当前下标以及是否折叠
    animationDuration 动画时间,默认为 kThemeAnimationDuration
    initialOpenPanelValue 默认打开的ExpansionPanelRadio的标识
    expandedHeaderPadding 展开后 Header 的 padding,默认为 _kPanelHeaderExpandedDefaultPadding
    dividerColor 分割线颜色
    elevation 阴影大小 不可以随意设置,具体看kElevationToShadow

    ExpansionPanelList.radio 对比ExpansionPanelList 默认构造函数,只增加了一个initialOpenPanelValue 属性

    4. ExpansionPanelList 实例

    示例1 ExpansionPanelList

    
    class MSExpansionPanelListDemo extends StatefulWidget {
      const MSExpansionPanelListDemo({Key? key}) : super(key: key);
    
      @override
      State<MSExpansionPanelListDemo> createState() =>
          _MSExpansionPanelListDemoState();
    }
    
    class _MSExpansionPanelListDemoState extends State<MSExpansionPanelListDemo> {
      List<MSExpansionPanelModel> _models = [];
      @override
      void initState() {
        _models.add(MSExpansionPanelModel("EP1", "Title EP1", false));
        _models.add(MSExpansionPanelModel("EP2", "Title EP2", false));
        _models.add(MSExpansionPanelModel("EP3", "Title EP3", false));
        _models.add(MSExpansionPanelModel("EP4", "Title EP4", false));
        _models.add(MSExpansionPanelModel("EP5", "Title EP5", false));
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text("ExpansionPanelListDemo")),
          body: SingleChildScrollView(
            child: _expansionPanelList(),
          ),
        );
      }
    
      List<ExpansionPanel> _initChildrenForExpansionPanel() {
        List<ExpansionPanel> _childrenForExpansionPanel = [];
        _models.forEach((element) {
          _childrenForExpansionPanel.add(_expansionPanelForModel(element));
        });
        return _childrenForExpansionPanel;
      }
    
      // 创建 ExpansionPanel
      ExpansionPanel _expansionPanelForModel(MSExpansionPanelModel model) {
        return ExpansionPanel(
          // header 构造函数
          headerBuilder: (context, isExpanded) {
            return Container(
              height: 56,
              alignment: Alignment.centerLeft,
              child: Text(model.title),
            );
          },
          // body 展开部分 Widget
          body: Container(
            height: 100,
            color: Colors.red,
          ),
          // 是否展开
          isExpanded: model.isExpanded,
          // 点击 header 是否可以展开收起,false
          canTapOnHeader: true,
          // 背景色
          backgroundColor: Colors.cyan[100],
        );
      }
    
      // 创建 ExpansionPanelList
      ExpansionPanelList _expansionPanelList() {
        return ExpansionPanelList(
          // 子控件数组 List<ExpansionPanel>
          children: _initChildrenForExpansionPanel(),
          // 分割线
          dividerColor: Colors.green,
          //动画时间,默认为 kThemeAnimationDuration
          animationDuration: Duration(milliseconds: 200),
          // 展开后 Header 的 padding,默认为 _kPanelHeaderExpandedDefaultPadding
          expandedHeaderPadding: EdgeInsets.all(8),
          // 展开收起回调函数,(index, isExpand){},返回当前下标以及是否折叠
          expansionCallback: (index, isExpand) {
            _models[index].isExpanded = !isExpand;
            setState(() {});
          },
          // 阴影大小
          elevation: 6,
        );
      }
    }
    
    class MSExpansionPanelModel {
      var value;
      String title;
      bool isExpanded;
      MSExpansionPanelModel(this.value, this.title, this.isExpanded);
    }
    
    129.gif

    示例2 ExpansionPanelList.radio

    
    class MSExpansionPanelListDemo2 extends StatefulWidget {
      const MSExpansionPanelListDemo2({Key? key}) : super(key: key);
    
      @override
      State<MSExpansionPanelListDemo2> createState() =>
          _MSExpansionPanelListDemo2State();
    }
    
    class _MSExpansionPanelListDemo2State extends State<MSExpansionPanelListDemo2> {
      List<MSExpansionPanelModel> _models = [];
      @override
      void initState() {
        _models.add(MSExpansionPanelModel("EP1", "Title EP1", false));
        _models.add(MSExpansionPanelModel("EP2", "Title EP2", false));
        _models.add(MSExpansionPanelModel("EP3", "Title EP3", false));
        _models.add(MSExpansionPanelModel("EP4", "Title EP4", false));
        _models.add(MSExpansionPanelModel("EP5", "Title EP5", false));
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text("ExpansionPanelListDemo2")),
          body: SingleChildScrollView(
            child: _expansionPanelListForRadio(),
          ),
        );
      }
    
      List<ExpansionPanelRadio> _initChildrenForExpansionPanelRadio() {
        List<ExpansionPanelRadio> _childrenForExpansionPanelRadio = [];
        _models.forEach((element) {
          _childrenForExpansionPanelRadio
              .add(_expansionPanelRadioForModle(element));
        });
        return _childrenForExpansionPanelRadio;
      }
    
      ExpansionPanelRadio _expansionPanelRadioForModle(
          MSExpansionPanelModel model) {
        return ExpansionPanelRadio(
          // 唯一标识
          value: model.value,
          // Header Widget 构造方法
          headerBuilder: (context, isExpanded) {
            return Container(
              height: 56,
              alignment: Alignment.centerLeft,
              child: Text(model.title),
            );
          },
          // 展开部分 Widget
          body: Container(
            height: 100,
            color: Colors.red,
          ),
          // 是否可以点击 header 用来展开收起,false
          canTapOnHeader: true,
          // 背景色
          backgroundColor: Colors.blue[100],
        );
      }
    
      ExpansionPanelList _expansionPanelListForRadio() {
        return ExpansionPanelList.radio(
          // 子控件数组,List< ExpansionPanelRadio >
          children: _initChildrenForExpansionPanelRadio(),
          // 展开后 Header 的 padding,默认为 _kPanelHeaderExpandedDefaultPadding
          expandedHeaderPadding: EdgeInsets.all(8),
          // 展开收起回调函数,(index, isExpand){},返回当前下标以及是否折叠
          expansionCallback: (index, isExpand) {
            print("expansionCallback index $index, isExpand $isExpand");
          },
          // 默认打开的ExpansionPanelRadio的标识
          initialOpenPanelValue: "EP2",
          // 动画时间,默认为 kThemeAnimationDuration
          animationDuration: Duration(milliseconds: 200),
          // 分割线颜色
          dividerColor: Colors.purple,
          // 阴影大小 不可以随意设置,具体看kElevationToShadow
          elevation: 6,
        );
      }
    }
    
    class MSExpansionPanelModel {
      var value;
      String title;
      bool isExpanded;
      MSExpansionPanelModel(this.value, this.title, this.isExpanded);
    }
    
    
    130.gif

    ExpansionPanelList.radio 仅可以展开一个 ExpansionPanel,ExpansionPanelList 默认构造函数可以展开多个

    5. 总结

    • 注意 ExpansionPanel 不可以直接作为子控件给到 body,否则会报错,这里用了 SingleChildScrollView 作为外层容器,使用 Column、ListView...等很多控件都可以。
    • 注意使用 ExpansionPanelList() 与 ExpansionPanelList.radio() 创建出来的 Widget,他们的 children 分别对应 <ExpansionPanel>,<ExpansionPanelRadio>,此处容易报错。
    • 注意 ExpansionPanelRadio.value 不可以相同,容易报错。

    相关文章

      网友评论

          本文标题:Flutter 组件之 ExpansionPanel、Expan

          本文链接:https://www.haomeiwen.com/subject/gkqxprtx.html