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
headerBuilder
:header
樣式body
:body
樣式isExpanded
:是否展開canTapOnHeader
:header
是否可點擊Creates an expansion panel to be used as a child for [ExpansionPanelList].
markdown
源碼註釋提到ExpansionPanel
不能單獨使用,要做爲ExpansionPanelList
的child
。ide
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個參數:函數
children
:ExpansionPanel
類型的數組expansionCallback
:點擊時的回調,會返回對應點擊的index
和當前isExpanded
的值animationDuration
:動畫持續時間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
能達到你想要的效果。ExpansionPanelRadio
是ExpansionPanel
的子類,多了一個value
做爲惟一標識,用來區分每一個ExpansionPanelRadio
。