Value not updating, keeps going back to original state
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;
});
});
},
),
],
),
],
);
},
);
}