如何制作自定义下拉菜单?

时间:2019-11-03 07:59:31

标签: flutter

如何在不更改DropdownButton宽度的情况下更改DropdownMenu的宽度和高度?我需要在按下DropdownButton时,然后DropdownMenu填充整个屏幕。如何更改DropdownMenu的位置,使其显示在按钮下方,但不与按钮重叠?

 String dropdownValue = '1';
Widget build(BuildContext context) {
   return MaterialApp(
     theme: new ThemeData(
       brightness: Brightness.light,
       primaryColor: Color...,
       accentColor: Colors...,
     ),
     debugShowCheckedModeBanner: false,
     home: Scaffold(
       appBar: AppBar(
         actions: <Widget>[
           Container(
             padding: EdgeInsets.fromLTRB(0.0, 5.0, 265.0, 0.0),
             child: CustomDropdownButton<String>(
               value: dropdownValue,
               icon:
                   Icon(Icons.arrow_drop_down, color: Colors...),
               iconSize: 21,
               elevation: 16,
               style:
                   TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
               underline: Container(
                 width: 200,
                 height: 2,
                 color: Colors...,
               ),
               onChanged: (String newValue) {
                 setState(() {
                   dropdownValue = newValue;
                 });
               },
               items: <String>[
                 '1',
                 '2',
                 '3',
                 '4'
               ].map<CustomDropdownMenuItem<String>>((String value) {
                 return CustomDropdownMenuItem<String>(
                   child: SizedBox(
                     width: 120.0,
                     child: Text("  " + value),
                   ),
                   value: value,
                 );
               }).toList(), ),)... 

1 个答案:

答案 0 :(得分:1)

DropdownButtonDropdownMenuItem不可能做到这一点,但是您可以使用PopupMenuButton属性使用PopupMenuItemoffset来实现。

这是一个简单的示例:

final _itemHeight = 80.0;
final _buttonHeight = 100.0;
final _values = [1, 2, 3, 4];
var _selectedValue = 1;

Offset _buildOffset() => Offset(
    0, _buttonHeight * 2 + _values.indexOf(_selectedValue) * _itemHeight * 2);

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(),
    body: PopupMenuButton(
      child: Container(
          color: Colors.yellow,
          height: _buttonHeight,
          width: 100,
          child: Center(child: Text('Item $_selectedValue'))),
      onSelected: (value) => setState(() => _selectedValue = value),
      initialValue: _selectedValue,
      offset: _buildOffset(),
      itemBuilder: (context) => _values
          .map((i) => PopupMenuItem(
                height: _itemHeight,
                child: Text('Item $i'),
                value: i,
              ))
          .toList(),
    ),
  );
}

编辑:不幸的是,即使您将PopupMenuItem的子项用SizedBox包裹并设置width来填充屏幕宽度,也不会之所以起作用,是因为PopupMenuItem有一个maxWidth_kMenuMaxWidth)。

这是一种使用AnimatedContainer进行类似操作的方法:

final _itemHeight = 80.0;
final _values = [1, 2, 3, 4];
var _selectedValue = 1;
var _expanded = false;

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(),
    body: Column(
      children: <Widget>[
        InkWell(
          child: Container(
            height: 100,
            width: 100,
            color: Colors.yellow,
            child: Text('Item $_selectedValue'),
          ),
          onTap: () => setState(() => _expanded = !_expanded),
        ),
        AnimatedContainer(
          duration: Duration(milliseconds: 250),
          height: _expanded ? _itemHeight * _values.length : 0,
          child: ListView(
            primary: false,
            children: _values
                .map(
                  (value) => SizedBox(
                    width: MediaQuery.of(context).size.width,
                    height: _itemHeight,
                    child: Material(
                      color: Colors.white,
                      child: InkWell(
                        child: Text('Item $value'),
                        onTap: () => setState(
                          () {
                            _selectedValue = value;
                            _expanded = false;
                          },
                        ),
                      ),
                    ),
                  ),
                )
                .toList(),
          ),
        ),
      ],
    ),
  );
}