Flutter:ExpansionTile 示例

2,186 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

Flutter 中的ExpansionTile小部件用于创建可扩展和可折叠的列表图块。本文将向您介绍 2 个在实践中使用该小部件的示例。第一个例子简短而简单,而第二个例子稍微复杂一些。

示例 1:单个 ExpansionTile

预览

此示例应用程序显示一个扩展磁贴,其子项是颜色列表:动画2

编码

生成上述示例的完整源代码:

// main.dart
import 'package:flutter/material.dart';
​
void main() {
  runApp(const MyApp());
}
​
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
​
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        // Hide the debug banner
        debugShowCheckedModeBanner: false,
        title: '大前端之旅',
        theme: ThemeData(primarySwatch: Colors.green),
        home: const HomeScreen());
  }
}
​
class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);
​
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('大前端之旅')),
      // Implement the ExpansionTile
      body: const ExpansionTile(
        title: Text('Colors'),
        subtitle: Text('Expand this tile to see its contents'),
        // Contents
        children: [
          ListTile(
              leading: CircleAvatar(
                backgroundColor: Colors.blue,
              ),
              title: Text('Blue')),
          ListTile(
              leading: CircleAvatar(
                backgroundColor: Colors.red,
              ),
              title: Text('Red')),
          ListTile(
              leading: CircleAvatar(
                backgroundColor: Colors.amber,
              ),
              title: Text('Amber')),
          ListTile(
              leading: CircleAvatar(
                backgroundColor: Colors.pink,
              ),
              title: Text('Pink')),
          ListTile(
              leading: CircleAvatar(
                backgroundColor: Colors.green,
              ),
              title: Text('Green')),
        ],
      ),
    );
  }
}
​

示例 2:ExpansionTile 和 ListView.builder

ExpansionTile 小部件通常与 ListView 一起使用。要保存和恢复 ExpansionTile 展开状态,我们必须给 ListView 的每个项目一个PageStorageKey,如下所示:

key: PageStorageKey(/* item id or something unique */),

应用预览

动画2

我们要构建的应用程序有一个呈现项目列表的列表视图。项目的数量很大,因此我们使用**ListView.builder构造函数来提高性能。每个项目都有一个标题和长文本内容。要查看该内容,用户必须展开项目图块。用户还可以使用相应的删除**按钮从列表中删除一个项目。

以下是它的工作原理:

编码

完整的源代码和解释:

// main.dart
import 'package:flutter/material.dart';
​
void main() {
  runApp(const MyApp());
}
​
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        // Remove the debug banner
        debugShowCheckedModeBanner: false,
        title: '大前端之旅',
        theme: ThemeData(
          primarySwatch: Colors.indigo,
        ),
        home: const HomePage());
  }
}
​
class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);
​
  @override
  _HomePageState createState() => _HomePageState();
}
​
class _HomePageState extends State<HomePage> {
  // Generate a list of list items
  // In real app, data often is fetched from an API or a database
  final List<Map<String, dynamic>> _items = List.generate(
      50,
      (index) => {
            "id": index,
            "title": "Item $index",
            "content":
                "This is the main content of item $index. It is very long and you have to expand the tile to see it."
          });
​
  // This function is called when a "Remove" button associated with an item is pressed
  void _removeItem(int id) {
    setState(() {
      _items.removeWhere((element) => element['id'] == id);
    });
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        duration: const Duration(milliseconds: 600),
        content: Text('Item with id #$id has been removed')));
  }
​
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: const Text('大前端之旅')),
        body: ListView.builder(
            itemCount: _items.length,
            itemBuilder: (_, index) {
              final item = _items[index];
              return Card(
                // this key is required to save and restore ExpansionTile expanded state
                key: PageStorageKey(item['id']),
                color: Colors.amber.shade200,
                elevation: 4,
                child: ExpansionTile(
                  // controlAffinity: ListTileControlAffinity.leading,
                  childrenPadding:
                      const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
                  expandedCrossAxisAlignment: CrossAxisAlignment.end,
                  maintainState: true,
                  title: Text(item['title']),
                  // contents
                  children: [
                    Text(item['content']),
                    // This button is used to remove this item
                    TextButton.icon(
                      onPressed: () => _removeItem(item['id']),
                      icon: const Icon(Icons.delete),
                      label: const Text(
                        'Remove',
                      ),
                      style: TextButton.styleFrom(primary: Colors.red),
                    )
                  ],
                ),
              );
            }));
  }
}
​

结论

我们已经检查了 Flutter 中的 ExpansionTile 小部件的几个示例。这个小部件真的很有帮助,并为您提供了一个简单的解决方案来安排您的应用程序中的内容。