如何创建Expanded面板

时间:2018-04-10 18:02:39

标签: dart flutter

HereExpanded panel的材料设计,如下所示:

enter image description here

我想与Flutter制作一个类似的,不确定我是否要从下面的代码开始或知道,以及如何完成它!

new ExpansionPanelList(
  children: <ExpansionPanel>[
    new ExpansionPanel(
      headerBuilder: (BuildContext context, bool isExpanded) {
            isExpanded = true;
            return new ListTile(
            // leading: item.iconpic,
            title: new Text(
            "First",
            textAlign: TextAlign.left,
            style: new TextStyle(
            fontSize: 20.0,
            fontWeight: FontWeight.w400,
            ),
            ));
          },
      body: new Text("school"),
      isExpanded: true,
    ),
    new ExpansionPanel(
      headerBuilder: (BuildContext context, bool isExpanded) {
        isExpanded = true;
        return new ListTile(
          // leading: item.iconpic,
            title: new Text(
              "Second",
              textAlign: TextAlign.left,
              style: new TextStyle(
                fontSize: 20.0,
                fontWeight: FontWeight.w400,
              ),
            ));
      },
      isExpanded: false,
      body: new Text("hospital"),
    ),
    new ExpansionPanel(
        headerBuilder: (BuildContext context, bool isExpanded) {
          isExpanded = true;
          return new ListTile(
            // leading: item.iconpic,
              title: new Text(
                "Third",
                textAlign: TextAlign.left,
                style: new TextStyle(
                  fontSize: 20.0,
                  fontWeight: FontWeight.w400,
                ),
              ));
        },
        body: new Text("va facility"),
        isExpanded: true)
    ]),

更新

我只需要开始并拥有空面板

enter image description here

3 个答案:

答案 0 :(得分:2)

这是一个工作示例(包括主要等等,因此您只需粘贴到文件中并运行)

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class ListItem {
  final WidgetBuilder bodyBuilder;
  final String title;
  final String subtitle;
  bool isExpandedInitially;

  ListItem({
    @required this.bodyBuilder,
    @required this.title,
    this.subtitle = "",
    this.isExpandedInitially = false,
  })  : assert(title != null),
        assert(bodyBuilder != null);

  ExpansionPanelHeaderBuilder get headerBuilder =>
      (context, isExpanded) => new Row(children: [
            new SizedBox(width: 100.0, child: new Text(title)),
            new Text(subtitle)
          ]);
}

class ExpansionList extends StatefulWidget {
  /// The items that the expansion list should display; this can change
  /// over the course of the object but probably shouldn't as it won't
  /// transition nicely or anything like that.
  final List<ListItem> items;

  ExpansionList(this.items) {
    // quick check to make sure there's no duplicate titles.
    assert(new Set.from(items.map((li) => li.title)).length == items.length);
  }

  @override
  State<StatefulWidget> createState() => new ExpansionListState();
}

class ExpansionListState extends State<ExpansionList> {
  Map<String, bool> expandedByTitle = new Map();

  @override
  Widget build(BuildContext context) {
    return new ExpansionPanelList(
      children: widget.items
          .map(
            (item) => new ExpansionPanel(
                headerBuilder: item.headerBuilder,
                body: new Builder(builder: item.bodyBuilder),
                isExpanded:
                    expandedByTitle[item.title] ?? item.isExpandedInitially),
          )
          .toList(growable: false),
      expansionCallback: (int index, bool isExpanded) {
        setState(() {
          expandedByTitle[widget.items[index].title] = !isExpanded;
        });
      },
    );
  }
}

void main() => runApp(
      new MaterialApp(
        home: new SingleChildScrollView(
          child: new SafeArea(
            child: new Material(
              child: new ExpansionList(
                [
                  new ListItem(
                      title: "Title 1",
                      subtitle: "Subtitle 1",
                      bodyBuilder: (context) => new Text("Body 1")),
                  new ListItem(
                      title: "Title 2",
                      subtitle: "Subtitle 2",
                      bodyBuilder: (context) => new Text("Body 1"),
                      isExpandedInitially: true)
                ],
              ),
            ),
          ),
        ),
      ),
    );

如果我不得不猜测,您错过了传入扩展到每个扩展标头的部分,以及跟踪每个扩展标头是否展开的部分。

我在这里采用了一种特殊方式,假设每个标题都是唯一的;你可以做类似的事情但依赖不同的属性。或者您可以在ExpansionListState等效的initState方法中构建所有内容。

This是一个完整的例子,几乎就是你帖子中图片中的确切用户界面。您只需从Play商店下载flutter gallery即可查看结果。他们采用了与我不同的方式(在initState方法中构建所有内容),并且它比我做的更复杂,但也值得理解。

希望有帮助=)

答案 1 :(得分:2)

如果您特别需要模仿从材料设计中引用的图像。您可能希望构建自己的自定义扩展面板。

我有一个使用AnimatedContainer向您展示如何创建展开和折叠效果的简单示例,您可以根据需要填充标题和正文部分。

enter image description here

class AnimateExpanded extends StatefulWidget {
  @override
  _AnimateExpandedState createState() => new _AnimateExpandedState();
}

class _AnimateExpandedState extends State<AnimateExpanded> {
  double _bodyHeight=0.0;
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      backgroundColor: Colors.grey[500],
      body: new SingleChildScrollView(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Card(
                    child: new Container(
                height: 50.0,
                child: new Row(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: <Widget>[
                    new IconButton(icon: new Icon(Icons.keyboard_arrow_down), onPressed: () {
                      setState((){
                        this._bodyHeight=300.0;
                      });
                    },)
                  ],
                ),
              ),
            ),
            new Card(
                 child: new AnimatedContainer(
                    child: new Row(
                          mainAxisAlignment: MainAxisAlignment.end,
                          crossAxisAlignment: CrossAxisAlignment.start,
                            children: <Widget>[
                              new IconButton(icon: new Icon(Icons.keyboard_arrow_up), onPressed: () {
                                  setState((){
                                    this._bodyHeight =0.0;

                                  });                                },),
                              ],
                            ),
                            curve: Curves.easeInOut,
                            duration: const Duration(milliseconds: 500),
                            height: _bodyHeight,
              // color: Colors.red,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

答案 2 :(得分:0)

您可以在ExpansionTile内使用ListView

        ListView(
              shrinkWrap: true,
              children: <Widget>[
                ExpansionTile(
                  backgroundColor: Colors.amber,
                  leading: Icon(Icons.event),
                  title: Text('Test1'),
                  children: <Widget>[
                    ListTile(title: Text('Title of the item')),
                    ListTile(
                      title: Text('Title of the item2'),
                    )
                  ],
                ),
                ExpansionTile(
                  title: Text('Test2'),
                  children: <Widget>[
                    ListTile(title: Text('Title of the item')),
                    ListTile(
                      title: Text('Title of the item2'),
                    )
                  ],
                )
              ],
            )