1

I'm trying to add a dropdown list, depending, for Android I'm using DropdownButton, for iOS a CupertinoPicker:

Platform.isAndroid
? AndroidSelect(
    items: ([0] + priceOptions),
    value: minPrice,
    zeroValue: 'no min',
    onChanged: (int? newVal) {
      setState(() {
        minPrice = newVal;
      });
    },
  )
: CupertinoSelect(
    initial: initialFromCupertino,
    onSelectedItemChanged: (index) {
      setState(() {
        minPrice = index == 0
            ? null
            : priceOptions[index - 1];
      });
    },
    options: priceOptionsFrom),

This code sits within a showModalBottomSheet.

The AndroidSelect is a separate stateless widget:

class AndroidSelect extends StatelessWidget {
  final List<int> items;

  final int? value;
  final String zeroValue;

  final void Function(int?) onChanged;
  const AndroidSelect(
      {Key? key,
      required this.items,
      required this.value,
      required this.onChanged,
      required this.zeroValue})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    print('building…');
    return Padding(
      padding: const EdgeInsets.all(40.0),
      child: DropdownButton<int>(
        onChanged: onChanged,
        value: value ?? 0,
        items: items.map<DropdownMenuItem<int>>((int value) {
          return DropdownMenuItem<int>(
            value: value,
            child: Text(
              value == 0 ? zeroValue : '$value CHF',
              style: const TextStyle(fontSize: 20),
            ),
          );
        }).toList(),
      ),
    );
  }
}

Now, when I change the dropdown, then the change is saved into minPrice (I have another widget which depends on it and this one does update), but the dropdown does not reflect the new value. The print('building…') is not called, when the setState() {minPrice=newVal}; is executed. Why is that?

hansaplast
  • 11,007
  • 2
  • 61
  • 75

1 Answers1

1

Return StatefulBuilder from showModalBottomSheet's builder and use its setState to update dialog UI.

showModalBottomSheet(
    context: context,
    builder: (c) {
      return StatefulBuilder(
        builder: (context, setStateSB) {
          return SizedBox(
            width: 300,
            height: 200,
            child: AndroidSelect(
              items: [1, 2, 4, 5],
              onChanged: (v) {
                setStateSB(() {
                  value = v;
                });
              },
              value: value,
              zeroValue: "nana",
            ),
          );
        },
      );
    });
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
  • indeed, that works! Can you point me to some documentation why this is needed? And why was it working for the CupertinoPicker but not for the DropdownButton? – hansaplast Jul 24 '22 at 09:41
  • 1
    You can check [this answer about show Dialog](https://stackoverflow.com/a/69609194/10157127) and `CupertinoPicker`(extends) itself a `StatefulWidget` and `AndroidSelect` is StatelessWidget. – Md. Yeasin Sheikh Jul 24 '22 at 09:47
  • I tried turning AndroidSelect into a stateful widget before but that didn't work… – hansaplast Jul 24 '22 at 09:51
  • I need to check that code structure before commenting on `StatefulWidget` situation. – Md. Yeasin Sheikh Jul 24 '22 at 09:54