📜  Flutter – 扩展面板(1)

📅  最后修改于: 2023-12-03 15:00:48.529000             🧑  作者: Mango

Flutter – 扩展面板

在Flutter中,扩展面板(Expansion Panel)是一个常用的交互控件,它可以让用户在需要时展开或收起一组相关的内容。本文将介绍如何使用Flutter中的扩展面板控件,让你轻松实现这个交互效果。

基本使用

在Flutter中,使用扩展面板控件需要引入ExpansionPanelExpansionPanelList两个控件。其中,ExpansionPanel表示一个可展开/收起的面板,而ExpansionPanelList则是所有扩展面板的容器。

以下是一个最简单的例子,它演示了如何使用ExpansionPanelList包含若干个ExpansionPanel,并在其中展示一些基本信息。详见代码片段:

class _MyHomePageState extends State<MyHomePage> {
  List<Item> _items = generateItems(10);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Expansion Panel Demo"),
      ),
      body: ExpansionPanelList(
        expansionCallback: (int index, bool isExpanded) {
          setState(() {
            _items[index].isExpanded = !isExpanded;
          });
        },
        children: _items.map<ExpansionPanel>((Item item) {
          return ExpansionPanel(
            headerBuilder: (BuildContext context, bool isExpanded) {
              return ListTile(
                title: Text(item.headerValue),
              );
            },
            body: ListTile(
              title: Text(item.expandedValue),
              subtitle: Text('弹出框'),
              trailing: Icon(Icons.add),
            ),
            isExpanded: item.isExpanded,
          );
        }).toList(),
      ),
    );
  }
}

class Item {
  String expandedValue;
  String headerValue;
  bool isExpanded;

  Item({this.expandedValue, this.headerValue, this.isExpanded = false});
}

List<Item> generateItems(int numberOfItems) {
  return List.generate(numberOfItems, (int index) {
    return Item(
      headerValue: 'Panel $index',
      expandedValue: 'This is item number $index',
    );
  });
}

代码解释:generateItems函数生成若干个Item对象,每个Item对象包含了一个常规信息和一个扩展信息,在下面的扩展面板中展示。ExpansionPanelList控件的expansionCallback参数接收的回调函数会在点击扩展面板时被调用,要求开发者更新isExpanded状态,从而触发UI的重绘。控件的children参数则接收一个List<ExpansionPanel>,表示所有面板的集合。每个ExpansionPanel需要配置headerBuilderbodyisExpanded这三个参数:

  • headerBuilder是一个回调函数,用于配置面板的头部,一般包含一个标题;
  • body用于配置面板展开时的内容,一般是一些复杂的布局或交互控件;
  • isExpanded表示面板是否展开,一般从数据模型中取而得。

在渲染完成后,我们得到一个可见的列表,展示了所有的扩展面板。现在,你可以尝试依次点击每个面板,打开会暴露出“弹出框”这个文本的对话框。

自定义展开效果

默认情况下,扩展面板在展开和收起时没有任何过渡效果,显得十分生硬。然而,我们可以通过使用ExpansionPanelRadioExpansionPanelRadioBuilder两个控件,来实现扩展面板的自定义展开/收起效果。

ExpansionPanelRadio表示带有状态转换效果的扩展面板,而ExpansionPanelRadioBuilder是它的一个高级版本,可以定制扩展面板的每个方面,包括展开状态、头部、展开内容等等。

下面是一个ExpansionPanelRadioBuilder的例子,它自定义了扩展面板的各个部分,除了可定制的headerbody外,还支持扩展面板和头部的渐变动画。你可以根据自己的需要,再次修改以下的代码片段:

List<Item> _data = generateItems(10);

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("Expansion Panel Demo"),
    ),
    body: SingleChildScrollView(
      child: Container(
        margin: EdgeInsets.all(24),
        child: ExpansionPanelList.radio(
          children: _data.map<ExpansionPanelRadio>((Item item) {
            return ExpansionPanelRadioBuilder(
              headerBackgroundColor: Colors.grey[300],
              headerRadius: BorderRadius.circular(12),
              canTapOnHeader: true,
              body: ListTile(
                title: Text(item.expandedValue),
                subtitle: Text('弹出框'),
                trailing: Icon(Icons.add),
              ),
              value: item,
              headerBuilder: (BuildContext context, Item value, bool isExpanded) {
                return Container(
                  padding: EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    gradient: isExpanded ? LinearGradient(
                      colors: [Colors.grey[400], Colors.grey[200]],
                      begin: Alignment.topCenter,
                      end: Alignment.bottomCenter,
                    ) : null,
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: Text(
                    value.headerValue,
                    style: TextStyle(
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                );
              },
            );
          }).toList(),
          expansionCallback: (int index, bool isExpanded) {
            setState(() {
              _data[index].isExpanded = !isExpanded;
            });
          },
        ),
      ),
    ),
  );
}
补充说明

Flutter中的扩展面板控件非常强大和灵活,它支持许多定制选项以及高效的动画效果,可以帮助开发者实现许多复杂的交互模式。如果想深入了解该控件的详细细节,建议查看官方文档和相关教程。