Let user settle picking value from CupertinoPicker(onSelectedItemChanged ), after that it should send call to API

919 Views Asked by At

I am using CupertinoWidget for iOS users to scroll through List and check the price of a currency. But when scroll happens, onSelectedItemChanged sends callback to API for every value from the list. I read the document but unable to understand what to do. It pleasing if there is an example.

In document it's mentioned as CupertinoPicker > onSelectedItemChanged property

This can be called during scrolls and during ballistic flings. To get the value only when the scrolling settles, use a NotificationListener, listen for ScrollEndNotification and read its FixedExtentMetrics.

 NotificationListener cupertinoPickerList() {
    List<Text> textWidgetList = [];
    for (String curreny in currenciesList) {
      textWidgetList.add(
        Text(
          curreny,
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      );
    }
    return NotificationListener<ScrollNotification>(
      onNotification: (scrollNotification) {
        if (scrollNotification is ScrollEndNotification) {
          return true;
        } else {
          return false;
        }
      },
      child: CupertinoPicker(
        itemExtent: 30,
        scrollController: FixedExtentScrollController(initialItem: 19),
        onSelectedItemChanged: (selectedIndex) {
          selectedCurreny = currenciesList[selectedIndex];
          updateUI(selectedCurreny);
          print(selectedCurreny);
        },
        children: textWidgetList,
      ),
    );
  }
2

There are 2 best solutions below

0
On

You can check if the metrics of the scrollNotification are of type FixedExtentMetrics. This type has the value itemIndex which you can use to determine which item is currently selected.

  return NotificationListener<ScrollNotification>(
    onNotification: (scrollNotification) {
      if (scrollNotification is ScrollEndNotification &&
      scrollNotification.metrics is FixedExtentMetrics) {
        (scrollNotification.metrics as FixedExtentMetrics).itemIndex; // Index of the list
        return true;
      } else {
        return false;
      }
    },
0
On

With the help of Juliantje15's code, here is a full solution:

final widget = NotificationListener<ScrollEndNotification>(
  onNotification: (notification) {
    if (notification.metrics is! FixedExtentMetrics) {
      return false;
    }

    final index = (notification.metrics as FixedExtentMetrics).itemIndex;

    // This would be your callback function. Could use items[index]
    // or something if that's more appropriate of course.
    onItemChanged(index);

    // False allows the event to bubble up further
    return false;
  },
  child: CupertinoPicker(
    itemExtent: 32,
    onSelectedItemChanged: null, // Attribute is marked required
    children: [Text('item1'), Text('item2'), Text('etc')], 
  ),
);

It seems quite sensible to want this, so I guess it's a bit strange that this isn't included as an (optional) default behavior. I guess you could turn the wrapper into a custom widget if it's needed more often.