MarcinusX / NumberPicker

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Value not updating, keeps going back to original state

Stilton0502 opened this issue · comments

Whenever I scroll, the number does not update with it and whenever I release it just reverts back to 0. When I print the values in onChanged it does update the values while I'm scrolling however when I release it animates back to the 0, consequently setting the value to 0 again.
Here is (the important parts of) my code:

int repsCompleted = 0;

NumberPicker(
                                            axis: Axis.horizontal,
                                            minValue: 0,
                                            maxValue: 40,
                                            value: repsCompleted,
                                            onChanged: (value) => setState(
                                                () => repsCompleted = value),
                                          )

Same thing on my end too:

late int _currentHeight;

@OverRide
void initState() {
_currentHeight = 122;
}

NumberPicker(
value: _currentHeight,
minValue: 0,
maxValue: 500,
onChanged: (value) => setState(() => _currentHeight = value),
),

I always feel sad when the first example from the docs doesn't work, maybe should look for another number picker.

I have same problem too.

btw just fyi I've went with a custom made picker with flutter native class: ListWheelScrollView and CupertinoPicker (which uses the ListWheelScrollView but have iOS default style).
So after that with some styling I really don't see the need of third party picker.

Here a one of the pickers:

ListWheelScrollView(
  controller: _heightWheelController,
  overAndUnderCenterOpacity: 0.5,
  useMagnifier: false,
  magnification: 1,
  diameterRatio: 4,
  itemExtent: 50,
  onSelectedItemChanged: (index) {
    HapticFeedback.lightImpact();
    int value = index + minHeight;
    _tempHeight = value;
  },
  physics: FixedExtentScrollPhysics(),
  children: [
    for (var i = minHeight; i < maxHeight; i++)
      Container(
        width: MediaQuery.of(context).size.width / 4,
        height: 50,
        child: Center(child: Text("$i cm")),
        decoration: BoxDecoration(
          borderRadius: new BorderRadius.all(const Radius.circular(6.0)),
          color: Colors.white12,
          border: Border.all(
            color: Colors.green,
            width: 3,
          ),
        ),
      ),
  ],
  ),

I found solution. Use StatefulBuilder.
Here is the code modified in the readme.md.

StatefulBuilder(
   builder: (context4, setState2) {
     return  Column(
       children: <Widget>[
         NumberPicker(
           value: _currentValue,
           minValue: 0,
           maxValue: 100,
           onChanged: (value) => setState2(() => _currentValue = value),
         ),
         Text('Current value: $_currentValue'),
       ],
     );
   },
 ),

@MikeMnD While I didn't know ListWheelScrollView exists and it does a similar job, I think its still far away from the Numberpicker in this package. E.g. is there a way to make it start at the beginning again once you reach the maximum?

@Bonsai11
Hi, my intention wasn't to diss your work, cause maybe in that time it was a fine solution. But at the moment i just think there are better/easy ones.
About your question:

E.g. is there a way to make it start at the beginning again once you reach the maximum?

Yes, using: ListWheelChildLoopingListDelegate here a stackoverflow topic and example: https://stackoverflow.com/questions/51118136/how-to-implement-cycle-wheel-scroll-list-widget

@MikeMnD Hi, I'm not the author, I'm just using this in my app aswell and like it so far. I prefer to use as little packages as possible aswell, so its always good to find native widgets for a certain problem.

I'm having the same issue too.
The 'onChanged' doesn't get triggered at all.
I'm using GetX if it may be helpful to troubleshoot.

  • get: ^4.3.5
  • numberpicker: ^2.1.1
Align(
                alignment: Alignment.center,
                child: NumberPicker(
                  value: c.pickedQuantity.toInt(),
                  minValue: 1,
                  maxValue: 100,
                  step: 1,
                  itemHeight: 50,
                  itemWidth: 50,
                  haptics: true,
                  itemCount: 5,
                  axis: Axis.horizontal,
                  onChanged: (value) => () {
                    print(value);
                    c.pickedQuantity = value as RxInt;
                  },
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(16),
                    border: Border.all(color: Colors.black),
                  ),
                ),
              ),

Just for reference, 'c' is my GetXController.

EDIT: I moved the picker code to a new file, and wrapped with a StatefulBuilder like this, but it's still not working as expected.

  Widget build(BuildContext context) {
    return StatefulBuilder(builder: (context, setState) {
      return NumberPicker(
        value: c.pickedQuantity.toInt(),
        minValue: 1,
        maxValue: 100,
        step: 1,
        itemHeight: 50,
        itemWidth: 50,
        haptics: true,
        itemCount: 5,
        axis: Axis.horizontal,
        onChanged: (value) => () {
          print(value);
          c.pickedQuantity = value as RxInt;
        },
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(16),
          border: Border.all(color: Colors.black),
        ),
      );
    });
  }
}

EDIT by the way, I would prefer to keep using GetX

@mlazzarotto I think you are missing to call setState in the onChanged callback, then it should work.

PS: Heard a lot of bad things about GetX, so be careful.

@mlazzarotto I think you are missing to call setState in the onChanged callback, then it should work.

PS: Heard a lot of bad things about GetX, so be careful.

I missed to say that in the controller.dart, i have this
RxInt pickedQuantity = 1.obs;

I believe that when I change the number, the onChanged should change the pickedQuantity, correct?

EDIT
It's working like you say, but in this way it's inconvenient, because I need to send the pickedQuantity from quantityPicker.dart back to new_item_page.dart and to the (not yet implemented) SQLite controller which will handle the record.
I'm using GetX because it's very simple to handle changes, at least for me because I'm a beginner.

I found solution. Use StatefulBuilder. Here is the code modified in the readme.md.

StatefulBuilder(
   builder: (context4, setState2) {
     return  Column(
       children: <Widget>[
         NumberPicker(
           value: _currentValue,
           minValue: 0,
           maxValue: 100,
           onChanged: (value) => setState2(() => _currentValue = value),
         ),
         Text('Current value: $_currentValue'),
       ],
     );
   },
 ),

I think most of the developers face this problem, and I think the questioner's problem will solve by trying this

this is maybe work for developers who had wrong with this.
in my case i have to use AlertDialog but you can edit it

void _showDialog() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          content: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              GestureDetector(
                child: Icon(
                  Icons.check_circle_outline_rounded,
                  size: 28,
                  color: AppTheme.buttonColorBlue,
                ),
                onTap: () {
                  Navigator.pop(context);
                  setState(() {
                    scale = numberPicker;
                  });
                },
              ),
              Text("test"),
              GestureDetector(
                child: SvgPicture.asset(
                  "assets/svg/delete.svg",
                  width: 20,
                  height: 20,
                  color: AppTheme.blackColor.withOpacity(.7),
                ),
                onTap: () {
                  Navigator.pop(context);
                },
              )
            ],
          ),
          actions: [
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  "g",
                  style: AppTheme.body1,
                ),
                StatefulBuilder(
                  builder: (BuildContext context, setState) {
                    return NumberPicker(
                        minValue: 100,
                        maxValue: 10000,
                        value: numberPicker,
                        step: 100,
                        // haptics: true,
                        onChanged: (value) {
                          setState((){
                            numberPicker = value;
                          });
                        });
                  },
                ),
              ],
            ),
          ],
        );
      },
    );
  }