如何在 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())