我把它作为inflating 砖的inflating 和坍塌的参考------Flutter - Collapsing ExpansionTile after choosing an item

我想要的是,如果我一个扩展瓷砖是打开的,而用户单击了另一个,那么其他打开的扩展瓷砖应该关闭.

snapshot of my app

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),
    );
  }
}

推荐答案

您可以使用ExpanablePanelList来执行展开和折叠视图. 使用expsionCallback保持活动状态以执行展开或折叠. 以下是工作示例

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'),),),
                ],
              ),
            );
          }),
    );
  }
}

Dart相关问答推荐

在 Dart 中使用隔离优于异步的优势

修复了 Flutter Dart 上 DataTable 的列和行标题

dart nullsafey 和使用旧包

创建默认应用时 FirebaseOptions 不能为空

如何保存 List 并使用 Hive 检索?

Dart中有没有类似python 字典(dictionary) struct ?

如何使用Flutter在按钮网格中滑动(swipe)/拖动(drag) 2 个或更多按钮

'T'、'f'、'E'、'e'、'→' 在 dart/flutter 文档中代表什么?

停止音频循环(audioplayers 包)

属性 'docs' 不能无条件访问,因为接收到的可能是 'null' Flutter

如何使我的对话框可滚动?

未定义命名参数child.在 Center() 构造函数中

如何在 Flutter 中为 PopupMenu 添加圆角边框?

从Dart中的另一个文件导入扩展名方法

使用Flatter向Cloud Firestore添加对象

如何在 Dart 中使用 char 类型?

何时使用polymer点击或点击?

Dart 中的多行字符串

Dart 会支持服务器端开发吗?

Dart 中的全局变量