Smith
Smith

Reputation: 591

How to make custom dropdownmenu?

How to change the width and height of the DropdownMenu without changing the width of the DropdownButton? I need when the DropdownButton is pressed then DropdownMenu fill the entire screen. How to change the position of the DropdownMenu so that it appears below the button, but does not overlap it?

 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(), ),)... 

Upvotes: 0

Views: 142

Answers (1)

Pablo Barrera
Pablo Barrera

Reputation: 10953

That's not possible to do with DropdownButton and DropdownMenuItem, but you could achieve this with PopupMenuButton and PopupMenuItem using the offset property.

Here is a quick example of how you could do it:

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(),
    ),
  );
}

Edit: Unfortunately even if you wrap the child of the PopupMenuItem with SizedBox and set a width to fill the screen width, it won't work because PopupMenuItem has a maxWidth (_kMenuMaxWidth).

Here is a way to make something similar using 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(),
          ),
        ),
      ],
    ),
  );
}

Upvotes: 1

Related Questions