我以此为参考来参考对展开图块的展开和折叠--------- Flutter-选择条目后的ExplansionTilesionTile
我想要的是,如果一个扩展图块处于打开状态,而用户单击另一个扩展图块,则其他打开的扩展图块应关闭。
import 'package:flutter/material.dart'; import 'package:meta/meta.dart'; void main() { runApp(new ExpansionTileSample()); } class ExpansionTileSample extends StatefulWidget { @override ExpansionTileSampleState createState() => new ExpansionTileSampleState(); } class ExpansionTileSampleState extends State<ExpansionTileSample> { final GlobalKey<AppExpansionTileState> expansionTile = new GlobalKey(); String foos = 'One'; @override Widget build(BuildContext context) { return new MaterialApp( home: new Scaffold( appBar: new AppBar( title: const Text('ExpansionTile'), ), body: GestureDetector( onTap: () { setState(() { // this.foos = 'One'; expansionTile.currentState.collapse(); }); }, child: Column( children: <Widget>[ new AppExpansionTile( key: expansionTile, title: new Text('1-3'), backgroundColor: Theme.of(context).accentColor.withOpacity(0.025), children: <Widget>[ new ListTile( title: const Text('One'), ), new ListTile( title: const Text('Two'), ), new ListTile( title: const Text('Three'), ), ]), new AppExpansionTile( title: new Text('4-6'), backgroundColor: Theme.of(context).accentColor.withOpacity(0.025), children: <Widget>[ new ListTile( title: const Text('four'), ), new ListTile( title: const Text('five'), ), new ListTile( title: const Text('six'), ), ]), new AppExpansionTile( title: new Text('6-9'), backgroundColor: Theme.of(context).accentColor.withOpacity(0.025), children: <Widget>[ new ListTile( title: const Text('seven'), ), new ListTile( title: const Text('eight'), ), new ListTile( title: const Text('nine'), ), ]), ], ), ), ), ); } } // --- Copied and slightly modified version of the ExpansionTile. const Duration _kExpand = const Duration(milliseconds: 200); class AppExpansionTile extends StatefulWidget { const AppExpansionTile({ Key key, this.leading, @required this.title, this.backgroundColor, this.onExpansionChanged, this.children: const <Widget>[], this.trailing, this.initiallyExpanded: false, }) : assert(initiallyExpanded != null), super(key: key); final Widget leading; final Widget title; final ValueChanged<bool> onExpansionChanged; final List<Widget> children; final Color backgroundColor; final Widget trailing; final bool initiallyExpanded; @override AppExpansionTileState createState() => new AppExpansionTileState(); } class AppExpansionTileState extends State<AppExpansionTile> with SingleTickerProviderStateMixin { AnimationController _controller; CurvedAnimation _easeOutAnimation; CurvedAnimation _easeInAnimation; ColorTween _borderColor; ColorTween _headerColor; ColorTween _iconColor; ColorTween _backgroundColor; Animation<double> _iconTurns; bool _isExpanded = false; @override void initState() { super.initState(); _controller = new AnimationController(duration: _kExpand, vsync: this); _easeOutAnimation = new CurvedAnimation(parent: _controller, curve: Curves.easeOut); _easeInAnimation = new CurvedAnimation(parent: _controller, curve: Curves.easeIn); _borderColor = new ColorTween(); _headerColor = new ColorTween(); _iconColor = new ColorTween(); _iconTurns = new Tween<double>(begin: 0.0, end: 0.5).animate(_easeInAnimation); _backgroundColor = new ColorTween(); _isExpanded = PageStorage.of(context)?.readState(context) ?? widget.initiallyExpanded; if (_isExpanded) _controller.value = 1.0; } @override void dispose() { _controller.dispose(); super.dispose(); } void expand() { _setExpanded(true); } void collapse() { _setExpanded(false); } void toggle() { _setExpanded(!_isExpanded); } void _setExpanded(bool isExpanded) { if (_isExpanded != isExpanded) { setState(() { _isExpanded = isExpanded; if (_isExpanded) _controller.forward(); else _controller.reverse().then<void>((Null value) { setState(() { // Rebuild without widget.children. }); }); PageStorage.of(context)?.writeState(context, _isExpanded); }); if (widget.onExpansionChanged != null) { widget.onExpansionChanged(_isExpanded); } } } Widget _buildChildren(BuildContext context, Widget child) { final Color borderSideColor = _borderColor.evaluate(_easeOutAnimation) ?? Colors.transparent; final Color titleColor = _headerColor.evaluate(_easeInAnimation); return new Container( decoration: new BoxDecoration( color: _backgroundColor.evaluate(_easeOutAnimation) ?? Colors.transparent, border: new Border( top: new BorderSide(color: borderSideColor), bottom: new BorderSide(color: borderSideColor), )), child: new Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ IconTheme.merge( data: new IconThemeData(color: _iconColor.evaluate(_easeInAnimation)), child: new ListTile( onTap: toggle, leading: widget.leading, title: new DefaultTextStyle( style: Theme .of(context) .textTheme .subhead .copyWith(color: titleColor), child: widget.title, ), trailing: widget.trailing ?? new RotationTransition( turns: _iconTurns, child: const Icon(Icons.expand_more), ), ), ), new ClipRect( child: new Align( heightFactor: _easeInAnimation.value, child: child, ), ), ], ), ); } @override Widget build(BuildContext context) { final ThemeData theme = Theme.of(context); _borderColor.end = theme.dividerColor; _headerColor ..begin = theme.textTheme.subhead.color ..end = theme.accentColor; _iconColor ..begin = theme.unselectedWidgetColor ..end = theme.accentColor; _backgroundColor.end = widget.backgroundColor; final bool closed = !_isExpanded && _controller.isDismissed; return new AnimatedBuilder( animation: _controller.view, builder: _buildChildren, child: closed ? null : new Column(children: widget.children), ); } }
您可以使用ExpandablePanelList来执行展开和折叠视图。使用expandingCallback保持活动状态以执行展开或折叠。这是工作示例
class TestExpandableView extends StatefulWidget { @override _TestExpandableViewState createState() => _TestExpandableViewState(); } class _TestExpandableViewState extends State<TestExpandableView> { int _activeMeterIndex; @override Widget build(BuildContext context) { return Container( child: new ListView.builder( itemCount: 2, itemBuilder: (BuildContext context, int i) { return Card( margin: const EdgeInsets.fromLTRB(10.0, 15.0, 10.0, 0.0), child: new ExpansionPanelList( expansionCallback: (int index, bool status) { setState(() { _activeMeterIndex = _activeMeterIndex == i ? null : i; }); }, children: [ new ExpansionPanel( isExpanded: _activeMeterIndex == i, headerBuilder: (BuildContext context, bool isExpanded) => new Container( padding: const EdgeInsets.only(left: 15.0), alignment: Alignment.centerLeft, child: new Text( 'list-$i', )), body: new Container(child: new Text('content-$i'),),), ], ), ); }), ); } }