如何在 Flutter 中自定义 DropdownButtons 和 DropdownMenuItems?
How should I customize DropdownButtons and DropdownMenuItems in Flutter?
默认 DropdownButton 和 DropdownMenuItems returns 浅灰色下拉菜单。我应该如何自定义下拉菜单(例如背景颜色、下拉菜单宽度)?我可以更改 DropdownButton 和 DropdownMenuItem 中的 style
属性,如下所示:
return new DropdownButton(
value: ...,
items: ...,
onChanged: ...,
style: new TextStyle(
color: Colors.white,
),
);
但这不会改变下拉菜单的背景颜色。
我应该复制 DropdownMenu 并扩展它吗? Flutter 是否计划在不久的将来为此小部件添加自定义?
您可以通过包装 DropdownButton
in a Theme
widget and overriding the canvasColor
来完成此操作。
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
int _value = 42;
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Theme(
data: Theme.of(context).copyWith(
canvasColor: Colors.blue.shade200,
),
child: new DropdownButton(
value: _value,
items: <DropdownMenuItem<int>>[
new DropdownMenuItem(
child: new Text('Foo'),
value: 0,
),
new DropdownMenuItem(
child: new Text('Bar'),
value: 42,
),
],
onChanged: (int value) {
setState(() {
_value = value;
});
},
),
),
),
);
}
}
正如 Collin 所说,您的 DropdownMenuItem
将跟随您的 ThemeData
class。它的 backgroundColor
不仅会匹配您 ThemeData
class 中的 canvasColor
,而且还会遵循相同的 TextStyle
.
所以,举个简单的例子:
new ThemeData(
fontFamily: "Encode Sans", //my custom font
canvasColor: _turquoise, //my custom color
//other theme data)
此外,如果你想控制菜单的width
,你可以给它的child
属性一个新的Container
并添加想要的width
,检查下面的 GIF,我从 width: 100.0
开始,然后在将其更改为 200.0
后重新加载,注意 width
是如何被操纵的,只要确保使用合适的宽度,以便当您在更复杂的布局中使用菜单时,您以后不会遇到溢出问题。
class TestPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title:new Text ("Test"),
),
body: new Center(
child: new DropdownButton(items: new List.generate(20, (int index){
return new DropdownMenuItem(child: new Container(
child: new Text ("Item#$index"),
width: 200.0, //200.0 to 100.0
));
})
, onChanged: null)
),
);
}
}
我能够更改下拉菜单的背景,方法是将其包装在 Container
中并设置 color
属性。
之前:
之后:
代码如下:
在小部件状态中定义这些值:
final items = ['One', 'Two', 'Three', 'Four'];
String selectedValue = 'Four';
然后使用此代码
Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(10)),
// dropdown below..
child: DropdownButton<String>(
value: selectedValue,
onChanged: (String newValue) =>
setState(() => selectedValue = newValue),
items: items
.map<DropdownMenuItem<String>>(
(String value) => DropdownMenuItem<String>(
value: value,
child: Text(value),
))
.toList(),
// add extra sugar..
icon: Icon(Icons.arrow_drop_down),
iconSize: 42,
underline: SizedBox(),
),
);
如果您希望 DropdownButton 填充它所在的 space,请使用 属性 isExpanded
并将其设置为 true
DropdownButton<String>(
isExpanded: true,
)
你可以在最新版本的 Flutter 中做一些非常简单的事情。
DropdownButton class 有一个名为 'dropdownColor' 的内置变量,可以直接为其分配您需要的任何颜色,而无需更改任何 'ThemeData'。也会自动更改下拉菜单项的颜色。
将其用于颜色
DropdownButtonFormField(
items: null,
onChanged: null,
dropdownColor: Colors.red,
),
你可以像这样用容器包裹它:
Container(
margin: const EdgeInsets.all(15.0),
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.white)
),
child: DropdownButton(
dropdownColor: Colors.white,
style: TextStyle(
color: Colors.black,
backgroundColor: Colors.white,
),
value: 'ar',
items: [
DropdownMenuItem(child: Text('English'), value: 'en'),
DropdownMenuItem(child: Text('العربية'), value: 'ar'),
],
),
)
输出:
https://api.flutter.dev/flutter/material/DropdownButton/style.html 将帮助您找出一些样式。
DropdownButton(
dropdownColor: Colors.grey,
value: this.repeatType,
onChanged: (String? value) {
print(value);
setState(() {
this.repeatType = value!;
});
},
selectedItemBuilder: (BuildContext context) {
return this.repeatTypes.map((String value) {
return Text(
this.repeatType,
style: const TextStyle(color: Colors.white),
);
}).toList();
},
items: this
.repeatTypes
.map((item) => DropdownMenuItem(
child: Text(
item,
style: TextStyle(color: Colors.green),
),
value: item,
))
.toList())
默认 DropdownButton 和 DropdownMenuItems returns 浅灰色下拉菜单。我应该如何自定义下拉菜单(例如背景颜色、下拉菜单宽度)?我可以更改 DropdownButton 和 DropdownMenuItem 中的 style
属性,如下所示:
return new DropdownButton(
value: ...,
items: ...,
onChanged: ...,
style: new TextStyle(
color: Colors.white,
),
);
但这不会改变下拉菜单的背景颜色。
我应该复制 DropdownMenu 并扩展它吗? Flutter 是否计划在不久的将来为此小部件添加自定义?
您可以通过包装 DropdownButton
in a Theme
widget and overriding the canvasColor
来完成此操作。
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
int _value = 42;
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Theme(
data: Theme.of(context).copyWith(
canvasColor: Colors.blue.shade200,
),
child: new DropdownButton(
value: _value,
items: <DropdownMenuItem<int>>[
new DropdownMenuItem(
child: new Text('Foo'),
value: 0,
),
new DropdownMenuItem(
child: new Text('Bar'),
value: 42,
),
],
onChanged: (int value) {
setState(() {
_value = value;
});
},
),
),
),
);
}
}
正如 Collin 所说,您的 DropdownMenuItem
将跟随您的 ThemeData
class。它的 backgroundColor
不仅会匹配您 ThemeData
class 中的 canvasColor
,而且还会遵循相同的 TextStyle
.
所以,举个简单的例子:
new ThemeData(
fontFamily: "Encode Sans", //my custom font
canvasColor: _turquoise, //my custom color
//other theme data)
此外,如果你想控制菜单的width
,你可以给它的child
属性一个新的Container
并添加想要的width
,检查下面的 GIF,我从 width: 100.0
开始,然后在将其更改为 200.0
后重新加载,注意 width
是如何被操纵的,只要确保使用合适的宽度,以便当您在更复杂的布局中使用菜单时,您以后不会遇到溢出问题。
class TestPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title:new Text ("Test"),
),
body: new Center(
child: new DropdownButton(items: new List.generate(20, (int index){
return new DropdownMenuItem(child: new Container(
child: new Text ("Item#$index"),
width: 200.0, //200.0 to 100.0
));
})
, onChanged: null)
),
);
}
}
我能够更改下拉菜单的背景,方法是将其包装在 Container
中并设置 color
属性。
之前:
之后:
代码如下:
在小部件状态中定义这些值:
final items = ['One', 'Two', 'Three', 'Four'];
String selectedValue = 'Four';
然后使用此代码
Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(10)),
// dropdown below..
child: DropdownButton<String>(
value: selectedValue,
onChanged: (String newValue) =>
setState(() => selectedValue = newValue),
items: items
.map<DropdownMenuItem<String>>(
(String value) => DropdownMenuItem<String>(
value: value,
child: Text(value),
))
.toList(),
// add extra sugar..
icon: Icon(Icons.arrow_drop_down),
iconSize: 42,
underline: SizedBox(),
),
);
如果您希望 DropdownButton 填充它所在的 space,请使用 属性 isExpanded
并将其设置为 true
DropdownButton<String>(
isExpanded: true,
)
你可以在最新版本的 Flutter 中做一些非常简单的事情。
DropdownButton class 有一个名为 'dropdownColor' 的内置变量,可以直接为其分配您需要的任何颜色,而无需更改任何 'ThemeData'。也会自动更改下拉菜单项的颜色。
将其用于颜色
DropdownButtonFormField(
items: null,
onChanged: null,
dropdownColor: Colors.red,
),
你可以像这样用容器包裹它:
Container(
margin: const EdgeInsets.all(15.0),
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.white)
),
child: DropdownButton(
dropdownColor: Colors.white,
style: TextStyle(
color: Colors.black,
backgroundColor: Colors.white,
),
value: 'ar',
items: [
DropdownMenuItem(child: Text('English'), value: 'en'),
DropdownMenuItem(child: Text('العربية'), value: 'ar'),
],
),
)
输出:
https://api.flutter.dev/flutter/material/DropdownButton/style.html 将帮助您找出一些样式。
DropdownButton(
dropdownColor: Colors.grey,
value: this.repeatType,
onChanged: (String? value) {
print(value);
setState(() {
this.repeatType = value!;
});
},
selectedItemBuilder: (BuildContext context) {
return this.repeatTypes.map((String value) {
return Text(
this.repeatType,
style: const TextStyle(color: Colors.white),
);
}).toList();
},
items: this
.repeatTypes
.map((item) => DropdownMenuItem(
child: Text(
item,
style: TextStyle(color: Colors.green),
),
value: item,
))
.toList())