下拉按钮状态管理 - Flutter
Dropdownbutton Statemanagement - Flutter
我想在 flutter 中创建一个带有多个下拉按钮的评估应用程序。下拉按钮应包含带有值的文本,例如:dropdownbutton1: "Text"; Value(2), dropdownbutton2: "文本"; Value2(4) 还有另一个按钮“评估”,如果我点击“评估”按钮,它应该转到下一个屏幕,下一个屏幕显示总值(它应该是 6= value(2 ) + 值 2(4).
我的下一个想法是状态管理,但我现在不知道该怎么做。
我在互联网上到处搜索,但找不到任何东西。
我是 Flutter 新手。有没有办法通过状态管理来实现它,它看起来会是什么样子?
您绝对应该实施一种状态管理,既用于页面之间的通信,也用于向下拉菜单提供数据,并保留下拉菜单中的选定值。
我的建议是使用像 Provider 状态管理策略这样简单的东西,并利用有助于侦听应用程序发生的变化的小部件。此策略使您的应用程序更加解耦,保持关注点的清晰分离并允许良好的维护。
您可以创建一个 Provided 服务(即 DropdownService),它将下拉菜单的值保存为下拉选项列表,以及两个保存到从下拉列表中选择的值(即 selectedFirstOption、selectedSecondOption)。在两个 DropDownButton 小部件上触发更改后,您可以触发小部件的通知以重建自身、更新其选择并保留所选值。
一个按钮将触发评估并导航到下一页,只有当 selectedFirstOption 和 selectedSecondOption 都不为 null 时,则下一页还使用提供的 DropdownService,提取为两个选择保留的数据,添加值并将其显示给用户。
我把一些东西放在一起作为例子来说明我的观点:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => DropdownService()
)
],
child: MyApp()
)
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<DropdownService>(
builder: (context, dropdownService, child) {
return Container(
padding: const EdgeInsets.all(30),
child: Column(
children: [
const Text('First dropdown:'),
DropdownButton<DropdownOption>(
value: dropdownService.selectedFirstOption,
icon: const Icon(Icons.arrow_drop_down),
elevation: 16,
onChanged: (DropdownOption? newValue) {
dropdownService.selectedFirstOption = newValue!;
},
items: dropdownService.firstDropdown.map((DropdownOption option) {
return DropdownMenuItem<DropdownOption>(
value: option,
child: Text(option.text!),
);
}).toList(),
),
const SizedBox(height: 20),
const Text('Second dropdown:'),
DropdownButton<DropdownOption>(
value: dropdownService.selectedSecondOption,
icon: const Icon(Icons.arrow_drop_down),
elevation: 16,
onChanged: (DropdownOption? newValue) {
dropdownService.selectedSecondOption = newValue!;
},
items: dropdownService.secondDropdown.map((DropdownOption option) {
return DropdownMenuItem<DropdownOption>(
value: option,
child: Text(option.text!),
);
}).toList(),
),
const SizedBox(height: 20),
Material(
color: Colors.amber,
child: TextButton(
onPressed: dropdownService.selectedFirstOption != null
&& dropdownService.selectedSecondOption != null ? () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => NextPage())
);
} : null,
child: const Text('Evaluate', style: TextStyle(color: Colors.black)
)
)
)
]
)
);
}
);
}
}
class NextPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
DropdownService dropdownService = Provider.of<DropdownService>(context, listen: false);
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('The result of ${dropdownService.selectedFirstOption!.text!} and ${dropdownService.selectedSecondOption!.text!}:'),
const SizedBox(height: 20),
Text('${dropdownService.selectedFirstOption!.value! + dropdownService.selectedSecondOption!.value!}',
style: const TextStyle(fontSize: 50)
),
],
),
),
);
}
}
class DropdownService extends ChangeNotifier {
List<DropdownOption> firstDropdown = [
DropdownOption(text: 'Value (5)', value: 5),
DropdownOption(text: 'Value (6)', value: 6),
DropdownOption(text: 'Value (7)', value: 7),
];
DropdownOption? _selectedFirstOption; // = DropdownOption(text: 'Select Value', value: -1);
DropdownOption? _selectedSecondOption; // = DropdownOption(text: 'Select Value', value: -1);
DropdownOption? get selectedFirstOption => _selectedFirstOption;
DropdownOption? get selectedSecondOption => _selectedSecondOption;
set selectedFirstOption(DropdownOption? value) {
_selectedFirstOption = value;
notifyListeners();
}
set selectedSecondOption(DropdownOption? value) {
_selectedSecondOption = value;
notifyListeners();
}
List<DropdownOption> secondDropdown = [
DropdownOption(text: 'Value (1)', value: 1),
DropdownOption(text: 'Value (2)', value: 2),
DropdownOption(text: 'Value (3)', value: 3),
];
}
class DropdownOption {
String? text;
double? value;
DropdownOption({ this.text, this.value });
}
如果您 运行 通过 DartPad.dev 此代码(也作为 Gist 提供),您应该看到以下输出:
我想在 flutter 中创建一个带有多个下拉按钮的评估应用程序。下拉按钮应包含带有值的文本,例如:dropdownbutton1: "Text"; Value(2), dropdownbutton2: "文本"; Value2(4) 还有另一个按钮“评估”,如果我点击“评估”按钮,它应该转到下一个屏幕,下一个屏幕显示总值(它应该是 6= value(2 ) + 值 2(4).
我的下一个想法是状态管理,但我现在不知道该怎么做。 我在互联网上到处搜索,但找不到任何东西。
我是 Flutter 新手。有没有办法通过状态管理来实现它,它看起来会是什么样子?
您绝对应该实施一种状态管理,既用于页面之间的通信,也用于向下拉菜单提供数据,并保留下拉菜单中的选定值。
我的建议是使用像 Provider 状态管理策略这样简单的东西,并利用有助于侦听应用程序发生的变化的小部件。此策略使您的应用程序更加解耦,保持关注点的清晰分离并允许良好的维护。
您可以创建一个 Provided 服务(即 DropdownService),它将下拉菜单的值保存为下拉选项列表,以及两个保存到从下拉列表中选择的值(即 selectedFirstOption、selectedSecondOption)。在两个 DropDownButton 小部件上触发更改后,您可以触发小部件的通知以重建自身、更新其选择并保留所选值。
一个按钮将触发评估并导航到下一页,只有当 selectedFirstOption 和 selectedSecondOption 都不为 null 时,则下一页还使用提供的 DropdownService,提取为两个选择保留的数据,添加值并将其显示给用户。
我把一些东西放在一起作为例子来说明我的观点:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => DropdownService()
)
],
child: MyApp()
)
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<DropdownService>(
builder: (context, dropdownService, child) {
return Container(
padding: const EdgeInsets.all(30),
child: Column(
children: [
const Text('First dropdown:'),
DropdownButton<DropdownOption>(
value: dropdownService.selectedFirstOption,
icon: const Icon(Icons.arrow_drop_down),
elevation: 16,
onChanged: (DropdownOption? newValue) {
dropdownService.selectedFirstOption = newValue!;
},
items: dropdownService.firstDropdown.map((DropdownOption option) {
return DropdownMenuItem<DropdownOption>(
value: option,
child: Text(option.text!),
);
}).toList(),
),
const SizedBox(height: 20),
const Text('Second dropdown:'),
DropdownButton<DropdownOption>(
value: dropdownService.selectedSecondOption,
icon: const Icon(Icons.arrow_drop_down),
elevation: 16,
onChanged: (DropdownOption? newValue) {
dropdownService.selectedSecondOption = newValue!;
},
items: dropdownService.secondDropdown.map((DropdownOption option) {
return DropdownMenuItem<DropdownOption>(
value: option,
child: Text(option.text!),
);
}).toList(),
),
const SizedBox(height: 20),
Material(
color: Colors.amber,
child: TextButton(
onPressed: dropdownService.selectedFirstOption != null
&& dropdownService.selectedSecondOption != null ? () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => NextPage())
);
} : null,
child: const Text('Evaluate', style: TextStyle(color: Colors.black)
)
)
)
]
)
);
}
);
}
}
class NextPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
DropdownService dropdownService = Provider.of<DropdownService>(context, listen: false);
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('The result of ${dropdownService.selectedFirstOption!.text!} and ${dropdownService.selectedSecondOption!.text!}:'),
const SizedBox(height: 20),
Text('${dropdownService.selectedFirstOption!.value! + dropdownService.selectedSecondOption!.value!}',
style: const TextStyle(fontSize: 50)
),
],
),
),
);
}
}
class DropdownService extends ChangeNotifier {
List<DropdownOption> firstDropdown = [
DropdownOption(text: 'Value (5)', value: 5),
DropdownOption(text: 'Value (6)', value: 6),
DropdownOption(text: 'Value (7)', value: 7),
];
DropdownOption? _selectedFirstOption; // = DropdownOption(text: 'Select Value', value: -1);
DropdownOption? _selectedSecondOption; // = DropdownOption(text: 'Select Value', value: -1);
DropdownOption? get selectedFirstOption => _selectedFirstOption;
DropdownOption? get selectedSecondOption => _selectedSecondOption;
set selectedFirstOption(DropdownOption? value) {
_selectedFirstOption = value;
notifyListeners();
}
set selectedSecondOption(DropdownOption? value) {
_selectedSecondOption = value;
notifyListeners();
}
List<DropdownOption> secondDropdown = [
DropdownOption(text: 'Value (1)', value: 1),
DropdownOption(text: 'Value (2)', value: 2),
DropdownOption(text: 'Value (3)', value: 3),
];
}
class DropdownOption {
String? text;
double? value;
DropdownOption({ this.text, this.value });
}
如果您 运行 通过 DartPad.dev 此代码(也作为 Gist 提供),您应该看到以下输出: