Flutter步进器插件expansion_stepper的使用
Flutter步进器插件expansion_stepper的使用
1. 插件简介
expansion_stepper
是一个用于创建现代水平和垂直步进器的Flutter插件,结合了 ExpansionTile
和 Stepper
组件,提供了Material设计风格的视觉体验。该插件允许开发者创建可扩展的卡片,每个卡片包含多个步骤,用户可以通过点击卡片来展开或折叠内容。
2. 功能特性
- 步进器卡片:应用展示了两个标记为 ‘A’ 和 ‘B’ 的扩展步进器卡片,每个卡片包含多个步骤,表示一个流程的不同阶段。
- 卡片交互:用户可以通过点击卡片来展开或折叠内容,还可以通过按钮编程控制其他卡片的状态(打开、关闭、切换)。
- 步进器子项:每个卡片包含多个步进器子项,表示流程中的不同步骤,如订单放置、订单准备、配送进度和订单交付。
- 调试信息:在
onTap
回调中包含了调试语句,可以在调试模式下打印消息到控制台。
3. 使用步骤
3.1 添加依赖
在 pubspec.yaml
文件的 dependencies
部分添加以下行:
dependencies:
...
expansion_stepper: ^latest_version
3.2 导入包
在你的Dart文件中导入 expansion_stepper
包:
import 'package:expansion_stepper/expansion_stepper.dart';
4. 完整示例代码
以下是一个完整的示例代码,展示了如何使用 ExpansionStepperCard
创建带有步进器的卡片:
import 'package:expansion_stepper/expansion_stepper.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Expansion Stepper Card Demo',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const MyHomePage(title: 'Expansion Stepper Card Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, this.title}) : super(key: key);
final String? title;
[@override](/user/override)
MyHomePageState createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
// 创建两个全局键,用于控制卡片的状态
final GlobalKey<ExpansionStepperCardState> cardA = GlobalKey();
final GlobalKey<ExpansionStepperCardState> cardB = GlobalKey();
[@override](/user/override)
Widget build(BuildContext context) {
// 定义按钮样式
final ButtonStyle flatButtonStyle = TextButton.styleFrom(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
);
return Scaffold(
appBar: AppBar(
title: Text(widget.title!),
),
body: ListView(
children: <Widget>[
// 卡片 A
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: ExpansionStepperCard(
key: cardA,
leading: const CircleAvatar(child: Text('A')), // 左侧图标
title: const Text('Tap me!'), // 标题
subtitle: const Text('I expand!'), // 副标题
stepperChildren: [
// 步骤 1: 订单已下单
StepperChildren(
title: const Text(
"Order Placed",
style: TextStyle(color: Colors.grey),
),
subtitle: const Text("Your order has been placed"),
iconWidget: Container(
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.all(Radius.circular(30)),
),
child: const Icon(Icons.looks_one, color: Colors.white),
),
onTap: () {
if (kDebugMode) {
print('Order Placed!');
}
},
padding: const EdgeInsets.only(left: 16),
topContent: const Divider(
thickness: 1,
color: Colors.black,
),
),
// 步骤 2: 准备中
StepperChildren(
title: const Text("Preparing"),
subtitle: const Text("Your order is being prepared"),
iconWidget: Container(
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.all(Radius.circular(30)),
),
child: const Icon(Icons.looks_two, color: Colors.white),
),
onTap: () {
if (kDebugMode) {
print('Order Preparing!');
}
},
padding: const EdgeInsets.only(left: 16),
),
// 步骤 3: 配送中
StepperChildren(
title: const Text("On the way"),
subtitle: const Text(
"Our delivery executive is on the way to deliver your item"),
iconWidget: Container(
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.all(Radius.circular(30)),
),
child: const Icon(Icons.looks_3, color: Colors.white),
),
onTap: () {
if (kDebugMode) {
print('On the way!');
}
},
padding: const EdgeInsets.only(left: 16),
),
// 步骤 4: 已送达
StepperChildren(
title: const Text("Delivered", style: TextStyle(color: Colors.grey)),
onTap: () {
if (kDebugMode) {
print('Delivered!');
}
},
padding: const EdgeInsets.only(left: 16),
),
],
children: [
const Divider(thickness: 1.0, height: 1.0),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Text(
"""Hi there, I'm a drop-in replacement for Flutter's ExpansionTile.
Use me any time you think your app could benefit from being just a bit more Material.
These buttons control the next card down!""",
style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 16),
),
),
),
ButtonBar(
alignment: MainAxisAlignment.spaceAround,
buttonHeight: 52.0,
buttonMinWidth: 90.0,
children: <Widget>[
TextButton(
style: flatButtonStyle,
onPressed: () {
cardB.currentState?.expand(); // 打开卡片 B
},
child: const Column(
children: <Widget>[
Icon(Icons.arrow_downward),
Padding(padding: EdgeInsets.symmetric(vertical: 2.0)),
Text('Open'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {
cardB.currentState?.collapse(); // 关闭卡片 B
},
child: const Column(
children: <Widget>[
Icon(Icons.arrow_upward),
Padding(padding: EdgeInsets.symmetric(vertical: 2.0)),
Text('Close'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {
cardB.currentState?.toggleExpansion(); // 切换卡片 B 的状态
},
child: const Column(
children: <Widget>[
Icon(Icons.swap_vert),
Padding(padding: EdgeInsets.symmetric(vertical: 2.0)),
Text('Toggle'),
],
),
),
],
),
],
),
),
// 卡片 B
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: ExpansionStepperCard(
key: cardB,
expandedTextColor: Colors.red, // 展开时文本颜色
leading: const CircleAvatar(child: Text('B')), // 左侧图标
title: const Text('Tap me!'), // 标题
subtitle: const Text('I expand, too!'), // 副标题
children: <Widget>[
const Divider(thickness: 1.0, height: 1.0),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Text(
"""Hi there, I'm a drop-in replacement for Flutter's ExpansionTile.
Use me any time you think your app could benefit from being just a bit more Material.
These buttons control the card above!""",
style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 16),
),
),
),
ButtonBar(
alignment: MainAxisAlignment.spaceAround,
buttonHeight: 52.0,
buttonMinWidth: 90.0,
children: <Widget>[
TextButton(
style: flatButtonStyle,
onPressed: () {
cardA.currentState?.expand(); // 打开卡片 A
},
child: const Column(
children: <Widget>[
Icon(Icons.arrow_downward),
Padding(padding: EdgeInsets.symmetric(vertical: 2.0)),
Text('Open'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {
cardA.currentState?.collapse(); // 关闭卡片 A
},
child: const Column(
children: <Widget>[
Icon(Icons.arrow_upward),
Padding(padding: EdgeInsets.symmetric(vertical: 2.0)),
Text('Close'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {
cardA.currentState?.toggleExpansion(); // 切换卡片 A 的状态
},
child: const Column(
children: <Widget>[
Icon(Icons.swap_vert),
Padding(padding: EdgeInsets.symmetric(vertical: 2.0)),
Text('Toggle'),
],
),
),
],
),
],
),
),
],
),
);
}
}
更多关于Flutter步进器插件expansion_stepper的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter步进器插件expansion_stepper的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用expansion_stepper
插件来实现步进器的示例代码。expansion_stepper
是一个流行的Flutter插件,用于创建具有扩展面板功能的步进器界面。
首先,确保你已经在pubspec.yaml
文件中添加了expansion_stepper
依赖:
dependencies:
flutter:
sdk: flutter
expansion_stepper: ^latest_version # 替换为最新版本号
然后运行flutter pub get
来安装依赖。
以下是一个完整的示例代码,展示了如何使用expansion_stepper
:
import 'package:flutter/material.dart';
import 'package:expansion_stepper/expansion_stepper.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Expansion Stepper Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Expansion Stepper Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: MyStepper(),
),
),
);
}
}
class MyStepper extends StatefulWidget {
@override
_MyStepperState createState() => _MyStepperState();
}
class _MyStepperState extends State<MyStepper> {
final List<Step> _steps = [
Step(
title: Text('Step 1: Personal Info'),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextField(
decoration: InputDecoration(labelText: 'First Name'),
),
SizedBox(height: 16),
TextField(
decoration: InputDecoration(labelText: 'Last Name'),
),
],
),
),
Step(
title: Text('Step 2: Contact Info'),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextField(
decoration: InputDecoration(labelText: 'Email'),
keyboardType: TextInputType.emailAddress,
),
SizedBox(height: 16),
TextField(
decoration: InputDecoration(labelText: 'Phone Number'),
keyboardType: TextInputType.phone,
),
],
),
),
Step(
title: Text('Step 3: Confirm'),
content: Text('Please review your information and confirm.'),
),
];
int _currentStep = 0;
void _nextStep() {
setState(() {
if (_currentStep < _steps.length - 1) {
_currentStep++;
}
});
}
void _previousStep() {
setState(() {
if (_currentStep > 0) {
_currentStep--;
}
});
}
@override
Widget build(BuildContext context) {
return ExpansionStepper(
steps: _steps,
currentStep: _currentStep,
controlsBuilder: (BuildContext context, {
VoidCallback? onNext,
VoidCallback? onPrevious,
VoidCallback? onCancel,
}) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
if (_currentStep > 0)
ElevatedButton(
onPressed: onPrevious,
child: Text('Previous'),
),
Expanded(child: SizedBox()),
if (_currentStep < _steps.length - 1)
ElevatedButton(
onPressed: onNext,
child: Text('Next'),
),
if (_currentStep == _steps.length - 1)
ElevatedButton(
onPressed: () {
// Handle the confirm action here
print('All steps completed!');
},
child: Text('Confirm'),
),
],
);
},
onStepContinue: _nextStep,
onStepCancel: () {
// Handle cancel action here if needed
setState(() {
_currentStep = 0;
});
},
);
}
}
在这个示例中,我们定义了一个包含三个步骤的步进器:
- 第一个步骤收集个人信息。
- 第二个步骤收集联系信息。
- 第三个步骤是一个确认步骤,显示用户输入的信息。
每个步骤都有一个标题和内容。内容部分包含了一些TextField
小部件,用于收集用户输入。底部控制按钮允许用户在步骤之间导航,并在最后一个步骤进行确认操作。
注意:ExpansionStepper
与标准的Stepper
有所不同,它允许每个步骤的内容在点击时展开和折叠。这个示例代码演示了基本的用法,你可以根据需要进行进一步的自定义和扩展。