I'm trying to select/scroll automatically to a particular element in ListWheelScrollView on a button click. It is working fine for the elements which are displayed in the current page. But I've been facing the issue when the list exceeds the screen due to lazy loading.
Due to widgets in ListWheelScrollView not rendered, when trying to scroll beyond the screen is throwing null error for the current context.
What I've tried:
Attempt 1: I've tried wrapping the ListWheelScrollView inside the SingleChildScrollView widget. Didn't solve the issue.
Attempt 2: Tried out using (scrollable_positioned_list ). It is for the ListView and not for ListWheelScrollView.
Here is my source code.
import 'package:flutter/material.dart';
// import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
void main() {
runApp(
const MaterialApp(home: StatefulWidgetsExample()), // use MaterialApp
);
}
class StatefulWidgetsExample extends StatefulWidget {
const StatefulWidgetsExample({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _StatefulWidgetsExampleState();
}
class _StatefulWidgetsExampleState extends State<StatefulWidgetsExample> {
final itemKey = GlobalKey();
final scrollController = ScrollController();
Future animateTo() async {
BuildContext? context = itemKey.currentContext;
scrollController.position.ensureVisible(
itemKey.currentContext!.findRenderObject()!,
duration: const Duration(seconds: 1),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("List Wheel"),
),
body: Column(
children: [
Expanded(
child: Center(
child: Row(
children: [
SizedBox(
height: 500,
width: 200,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: SizedBox(
height: 500,
width: 200,
child: ListWheelScrollView(
controller: scrollController,
itemExtent: 100,
children: <Widget>[
const MaterialButton(
onPressed: null,
child: Text(
"Item 1",
textAlign: TextAlign.start,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 25),
),
),
const MaterialButton(
onPressed: null,
child: Text(
"Item 2",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 25),
),
),
const MaterialButton(
onPressed: null,
child: Text(
"Item 3",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 25),
),
),
const MaterialButton(
onPressed: null,
child: Text(
"Item 4",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 25),
),
),
Container(
alignment: Alignment.center,
key: itemKey,
child: const MaterialButton(
onPressed: null,
child: Text(
"Item 5",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 25),
),
),
),
const MaterialButton(
onPressed: null,
child: Text(
"Item 6",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 25),
),
),
const MaterialButton(
onPressed: null,
child: Text(
"Item 7",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 25),
),
),
const MaterialButton(
onPressed: null,
child: Text(
"Item 8",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 25),
),
),
],
clipBehavior: Clip.hardEdge,
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: MaterialButton(
color: Colors.red,
onPressed: animateTo,
child: const Text("Animate to"),
),
),
],
),
),
),
],
),
);
}
}
Any help/suggestion would be highly appreciated. Thank you!
After doing a bit of ground work, I've figured out that it can be done through FixedExtentScrollController
.
Here is the complete example if someone is facing the same issue.
void main() {
runApp(
const MaterialApp(home: StatefulWidgetsExample()), // use MaterialApp
);
}
class StatefulWidgetsExample extends StatefulWidget {
const StatefulWidgetsExample({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _StatefulWidgetsExampleState();
}
class _StatefulWidgetsExampleState extends State<StatefulWidgetsExample> {
final FixedExtentScrollController scrollController =
FixedExtentScrollController();
@override
void dispose() {
scrollController.dispose();
super.dispose();
}
Widget buildCard(int i) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 200,
height: 200,
color: Colors.red,
child: Center(
child: Text(
"Widget: " + i.toString(),
),
),
),
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("List Wheel"),
),
body: ListWheelScrollView(
controller: scrollController,
itemExtent: 250,
physics: const FixedExtentScrollPhysics(),
squeeze: 0.9,
children: [
buildCard(0),
buildCard(1),
buildCard(2),
buildCard(3),
buildCard(4),
buildCard(5),
buildCard(6),
buildCard(7),
buildCard(8),
buildCard(9),
buildCard(10),
buildCard(11),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
scrollController.animateToItem(9,
duration: const Duration(seconds: 1), curve: Curves.easeInOut);
},
child: const Icon(Icons.ac_unit),
),
);
}
}