Flutter 之 ExpansionPanel

介紹

ExpansionPanel官方提供的一個擴展面板的控件,使用它能夠輕鬆實現展開收起的功能。數組

ExpansionPanel

ExpansionPanel({
    @required this.headerBuilder,
    @required this.body,
    this.isExpanded = false,
    this.canTapOnHeader = false,
  }) : assert(headerBuilder != null),
       assert(body != null),
       assert(isExpanded != null),
       assert(canTapOnHeader != null);
複製代碼

ExpansionPanel的構造函數有4個參數:bash

  1. headerBuilderheader樣式
  2. bodybody樣式
  3. isExpanded:是否展開
  4. canTapOnHeaderheader是否可點擊

ExpansionPanelList

Creates an expansion panel to be used as a child for [ExpansionPanelList].markdown

源碼註釋提到ExpansionPanel不能單獨使用,要做爲ExpansionPanelListchildide

const ExpansionPanelList({
    Key key,
    this.children = const <ExpansionPanel>[],
    this.expansionCallback,
    this.animationDuration = kThemeAnimationDuration,
  }) : assert(children != null),
       assert(animationDuration != null),
       _allowOnlyOnePanelOpen = false,
       initialOpenPanelValue = null,
       super(key: key);
複製代碼

ExpansionPanelList的構造函數有3個參數:函數

  1. childrenExpansionPanel類型的數組
  2. expansionCallback:點擊時的回調,會返回對應點擊的index和當前isExpanded的值
  3. animationDuration:動畫持續時間

效果

Demo代碼

class Item {
  String familyName;
  List<String> fullName;
  bool isExpanded;
  
  Item(this.familyName, this.fullName, this.isExpanded);
}

List<Item> getDataSource() {
  return [
    Item('張', ['張一一', '張二二', '張三三', '張四四'], false),
    Item('王', ['王一一', '王二二', '王三三', '王四四'], false),
    Item('李', ['李一一', '李二二', '李三三', '李四四'], false),
    Item('趙', ['趙一一', '趙二二', '趙三三', '趙四四'], false),
    Item('周', ['週一一', '週二二', '週三三', '週四四'], false),
    Item('吳', ['吳一一', '吳二二', '吳三三', '吳四四'], false),
    Item('孫', ['孫一一', '孫二二', '孫三三', '孫四四'], false),
  ];
}
複製代碼
List<Item> _dataSource = getDataSource();
  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: ExpansionPanelList(
        expansionCallback: (int index, bool isExpanded) {
          setState(() {
            _dataSource[index].isExpanded = !isExpanded;
          });
        },
        children: _dataSource.map<ExpansionPanel>((Item item) {
          return ExpansionPanel(
            canTapOnHeader: true,
            isExpanded: item.isExpanded,
            headerBuilder: (BuildContext context, bool isExpanded) {
              return ListTile(
                title: Text(item.familyName),
              );
            },
            body: ListView.separated(
              itemBuilder: (BuildContext context, int index) {
                return Container(
                  padding: EdgeInsets.fromLTRB(15, 10, 15, 10),
                  child: Text(item.fullName[index]),
                );
              },
              separatorBuilder: (BuildContext context, int index) {
                return new Container(height: 1.0, color: Color(0xfff2f2f2));
              },
              itemCount: item.fullName.length,
              shrinkWrap: true,
              physics: NeverScrollableScrollPhysics(),
            ),
          );
        }).toList(),
        animationDuration: Duration(microseconds: 100),
      ),
    );
  }
複製代碼

總結

代碼簡單易懂不作多解釋,有幾個須要注意的點這裏總結下:動畫

  • build方法直接return一個ExpansionPanelList會發現沒有任何內容展現。 Log提示:RenderListBody must have unlimited space along its main axis.也就是說要保持RenderListBody的主軸上必須有無限的空間。這裏咱們在外面包一層SingleChildScrollView來達到主軸無限的空間的目的。ui

  • 注意ListView.separated中的屬性設置。this

shrinkWrap: true, // 多用於嵌套`listView`內容大小不肯定的狀況
  physics: NeverScrollableScrollPhysics(), // 禁止滾動,這裏想要的效果是展開後跟着ExpansionPanelList一塊兒滾動而不是內部ListView單獨滾動
複製代碼
  • 若是你的需求是隻能展開一個,點擊時其餘展開的自動收起的狀況,使用ExpansionPanelList.radio配合ExpansionPanelRadio能達到你想要的效果。ExpansionPanelRadioExpansionPanel的子類,多了一個value做爲惟一標識,用來區分每一個ExpansionPanelRadio
相關文章
相關標籤/搜索