The code is a button that on pressed shows a modal bottom sheet (with showModalBottomSheet()) with a scrollable list of months that the user can pick, using a ListWheelScrollView widget (with method use.Delegate).
I was having trouble with the state that was not getting updated as the wheel was being scrolled, so I tried to print it. The print (available in the code) showed that the state is updating but really weirdly. I'm using Riverpod as a State Management solution, but I don't mind using stateful widgets, so if it's easier for you, don't hesitate.
I tried to print the state at multiple moments of the run in the console, but I can't understand the logic it follows.
If you could find a way to update the state, or if you know something that could help me, it would be amazing that you share it with me.
I tried to make my problem as minimal as I could so that you can find easily the heart of the issue. Here it is :
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
const List<String> _months = <String>[
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
void main() => runApp(ProviderScope(child: MyApp()));
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MainPage(),
);
}
}
int monthIndex = (DateTime.now().month);
final monthIndexProvider = StateProvider(((ref) => monthIndex));
class MainPage extends ConsumerWidget {
const MainPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final int month = ref.watch(monthIndexProvider);
return Scaffold(
body: Center(
child: ElevatedButton(
child: Text(month.toString()),
onPressed: () async {
await showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 300,
child: ListWheelScrollView.useDelegate(
itemExtent: 50,
perspective: 0.001,
diameterRatio: 1.6,
physics: FixedExtentScrollPhysics(),
squeeze: 1.0,
overAndUnderCenterOpacity: 0.2,
useMagnifier: true,
magnification: 1.3,
onSelectedItemChanged: (index) {
ref.read(monthIndexProvider.notifier).state = index;
print(month); // This is the print where I want to get the state of month but it isn't the right one.
},
childDelegate: ListWheelChildBuilderDelegate(
childCount: 12,
builder: (context, index) {
return Container(
child: Text(_months[index]),
);
})));
},
);
}),
),
);
}
}
CodePudding user response:
Inner state of showModalBottomSheet
is not being updated. You can update it by using StatefulBuilder
. More info here.
Here is the full solution:
final monthIndex = (DateTime.now().month);
final monthIndexProvider = StateProvider(((ref) => monthIndex));
class MainPage extends ConsumerWidget {
const MainPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
body: Center(
child: ElevatedButton(
child: Text(ref.watch(monthIndexProvider).toString()),
onPressed: () async {
await showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setStateModal) {
final int month = ref.watch(monthIndexProvider);
return SizedBox(
height: 300,
child: ListWheelScrollView.useDelegate(
itemExtent: 50,
perspective: 0.001,
diameterRatio: 1.6,
physics: const FixedExtentScrollPhysics(),
squeeze: 1.0,
overAndUnderCenterOpacity: 0.2,
useMagnifier: true,
magnification: 1.3,
onSelectedItemChanged: (index) {
ref.read(monthIndexProvider.notifier).state = index;
setStateModal(() {});
print(month);
},
childDelegate: ListWheelChildBuilderDelegate(
childCount: 12,
builder: (context, index) {
return Text(_months[index]);
},
),
),
);
},
);
},
);
},
),
),
);
}
}