如何在 flutter 中使用 DropdownButton 制作 Tree Select Box
How to make Tree Select Box with DropdownButton in flutter
我想在 Flutter 中制作一个带有 DropDownButton 的 Select 框。
但我无法为它制定完美的算法。
希望得到Flutter高手的大力帮助。
谢谢。
Screenshot of current implementation
我已经自己解决了这个问题。
这是我的代码。
不过希望Flutter高手有更好的解决方案。
addTaskList(){
taskChildrenList.clear();
print(selectedTaskList.length);
selectedTaskList.forEach((task){
taskChildrenList.add(Card(
margin: EdgeInsets.symmetric(vertical: 5),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("${AppLanguage.selectTaskLabel()} ${task[0].label}",style: TextStyle(fontSize: 15,fontWeight: FontWeight.bold),),
Flexible(
child: FittedBox(
child: DropdownButton<JustificationTask>(
value: selectedTasks.length==task[0].label-1?null:selectedTasks[task[0].label-1],
icon: Icon(Icons.chevron_right),
iconSize: 25,
elevation: 16,
style: TextStyle(color: Colors.black),
underline: Container(height: 1, color: Colors.transparent,),
onChanged: (JustificationTask value) {
setState(() {
selectedTaskList.removeRange(value.label, selectedTaskList.length);
selectedTasks.removeRange(value.label-1, selectedTasks.length);
selectedTasks.add(value);
if(value.children.isNotEmpty){
selectedTaskList.add(value.children);
selectedTask=null;
}else{
selectedTask=value;
equipment=null;
}
});
},
items: task.map<DropdownMenuItem<JustificationTask>>((JustificationTask value) {
return DropdownMenuItem<JustificationTask>(
value: value,
child: SizedBox(width:MediaQuery.of(context).size.width*0.4,child: Text("${taskName(value)}",style: TextStyle(fontSize: 20),)),
);
}).toList(),
hint: SizedBox(width:MediaQuery.of(context).size.width*0.4,child: Text(AppLanguage.task(),style: TextStyle(fontSize: 20))),
isExpanded: false,
),
),
),
],
),
),
),);
});
}
对于其他 运行 遇到此问题但没有得到此处答案帮助的人...我编写了一个简单的应用程序来完成此操作,select 使用动态下拉菜单从树中选择一个项目纽扣。这是完整的代码:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class Node {
final String name;
final List<Node> children;
Node({this.name, this.children});
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Animal Classification'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> treeLevels = ['Phylum', 'Class', 'Species'];
List<Node> selectedNodes = [
Node(name: 'Animal Kingdom', children: <Node>[
Node(name: 'Vertebrates', children: <Node>[
Node(name: 'Fish'),
Node(name: 'Amphibians'),
Node(name: 'Reptiles'),
Node(name: 'Birds'),
Node(name: 'Mammals', children: <Node>[
Node(name: 'Bats'),
Node(name: 'Carnivores'),
Node(name: 'Birds'),
]),
]),
Node(name: 'Annelids'),
Node(name: 'Molluscs'),
Node(name: 'Nematodes'),
Node(name: 'Arthropods', children: <Node>[
Node(name: 'Crustaceans'),
Node(name: 'Arachnids'),
Node(name: 'Insects'),
Node(name: 'Myriapods'),
]),
]),
];
@override
Widget build(BuildContext context) {
List<Widget> items = [];
for (var i = 0; i < selectedNodes.length; i++) {
if (selectedNodes[i] != null &&
(selectedNodes[i].children?.isNotEmpty ?? false)) {
items.add(
Text(treeLevels[i], style: Theme.of(context).textTheme.headline5));
items.add(DropdownButtonFormField(
value: selectedNodes.length > i + 1 ? selectedNodes[i + 1] : null,
items: selectedNodes[i]
.children
.map((node) => DropdownMenuItem(
value: node,
child: Text(node.name),
))
.toList(),
onChanged: (selected) => setState(() {
selectedNodes.removeRange(i + 1, selectedNodes.length);
selectedNodes.add(selected);
}),
));
items.add(SizedBox(height: 16.0)); // Padding
}
}
return Scaffold(
appBar: AppBar(
title: Center(child: Text(widget.title)),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
children: items,
),
));
}
}
我想在 Flutter 中制作一个带有 DropDownButton 的 Select 框。 但我无法为它制定完美的算法。 希望得到Flutter高手的大力帮助。 谢谢。
Screenshot of current implementation
我已经自己解决了这个问题。 这是我的代码。 不过希望Flutter高手有更好的解决方案。
addTaskList(){
taskChildrenList.clear();
print(selectedTaskList.length);
selectedTaskList.forEach((task){
taskChildrenList.add(Card(
margin: EdgeInsets.symmetric(vertical: 5),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("${AppLanguage.selectTaskLabel()} ${task[0].label}",style: TextStyle(fontSize: 15,fontWeight: FontWeight.bold),),
Flexible(
child: FittedBox(
child: DropdownButton<JustificationTask>(
value: selectedTasks.length==task[0].label-1?null:selectedTasks[task[0].label-1],
icon: Icon(Icons.chevron_right),
iconSize: 25,
elevation: 16,
style: TextStyle(color: Colors.black),
underline: Container(height: 1, color: Colors.transparent,),
onChanged: (JustificationTask value) {
setState(() {
selectedTaskList.removeRange(value.label, selectedTaskList.length);
selectedTasks.removeRange(value.label-1, selectedTasks.length);
selectedTasks.add(value);
if(value.children.isNotEmpty){
selectedTaskList.add(value.children);
selectedTask=null;
}else{
selectedTask=value;
equipment=null;
}
});
},
items: task.map<DropdownMenuItem<JustificationTask>>((JustificationTask value) {
return DropdownMenuItem<JustificationTask>(
value: value,
child: SizedBox(width:MediaQuery.of(context).size.width*0.4,child: Text("${taskName(value)}",style: TextStyle(fontSize: 20),)),
);
}).toList(),
hint: SizedBox(width:MediaQuery.of(context).size.width*0.4,child: Text(AppLanguage.task(),style: TextStyle(fontSize: 20))),
isExpanded: false,
),
),
),
],
),
),
),);
});
}
对于其他 运行 遇到此问题但没有得到此处答案帮助的人...我编写了一个简单的应用程序来完成此操作,select 使用动态下拉菜单从树中选择一个项目纽扣。这是完整的代码:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class Node {
final String name;
final List<Node> children;
Node({this.name, this.children});
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Animal Classification'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> treeLevels = ['Phylum', 'Class', 'Species'];
List<Node> selectedNodes = [
Node(name: 'Animal Kingdom', children: <Node>[
Node(name: 'Vertebrates', children: <Node>[
Node(name: 'Fish'),
Node(name: 'Amphibians'),
Node(name: 'Reptiles'),
Node(name: 'Birds'),
Node(name: 'Mammals', children: <Node>[
Node(name: 'Bats'),
Node(name: 'Carnivores'),
Node(name: 'Birds'),
]),
]),
Node(name: 'Annelids'),
Node(name: 'Molluscs'),
Node(name: 'Nematodes'),
Node(name: 'Arthropods', children: <Node>[
Node(name: 'Crustaceans'),
Node(name: 'Arachnids'),
Node(name: 'Insects'),
Node(name: 'Myriapods'),
]),
]),
];
@override
Widget build(BuildContext context) {
List<Widget> items = [];
for (var i = 0; i < selectedNodes.length; i++) {
if (selectedNodes[i] != null &&
(selectedNodes[i].children?.isNotEmpty ?? false)) {
items.add(
Text(treeLevels[i], style: Theme.of(context).textTheme.headline5));
items.add(DropdownButtonFormField(
value: selectedNodes.length > i + 1 ? selectedNodes[i + 1] : null,
items: selectedNodes[i]
.children
.map((node) => DropdownMenuItem(
value: node,
child: Text(node.name),
))
.toList(),
onChanged: (selected) => setState(() {
selectedNodes.removeRange(i + 1, selectedNodes.length);
selectedNodes.add(selected);
}),
));
items.add(SizedBox(height: 16.0)); // Padding
}
}
return Scaffold(
appBar: AppBar(
title: Center(child: Text(widget.title)),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
children: items,
),
));
}
}