How to stop scrolling of ListWheelScrollView
for the first index.
Expected Output : -
ListWheelScrollView
should stop scrolling when it encounters a disabled item or the first index of ListView. Scroll index should not count the first index, that is it should not move further or to the disabled index.
Expected Output GIF : -
Code : -
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'List',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: const List(),
);
}
}
class List extends StatefulWidget {
const List({Key? key}) : super(key: key);
@override
_ListState createState() => _ListState();
}
class _ListState extends State<List> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("List"),
backgroundColor: Colors.green,
),
body: Center(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
RotatedBox(
quarterTurns: 1,
child: SizedBox(
height: 600,
width: 800,
child: ListWheelScrollView(
itemExtent: 100,
physics: const FixedExtentScrollPhysics(),
onSelectedItemChanged: (value) {},
children: [
for (int i = 0; i < 4; i++) ...[
Container(
color: i != 3 ? Colors.green[200] : Colors.red[200],
height: 70,
width: 70,
alignment: Alignment.center,
child: RotatedBox(
quarterTurns: -1,
child: Text(i != 3 ? "Enabled" : "Disabled")),
)
]
]),
),
),
const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
],
),
));
}
}
One solution provided : -
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'List',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: const ScrollingList(),
);
}
}
class ScrollingList extends StatefulWidget {
const ScrollingList({Key? key}) : super(key: key);
@override
_ScrollingListState createState() => _ScrollingListState();
}
class _ScrollingListState extends State<ScrollingList> {
final controller = FixedExtentScrollController();
final children = [
for (int i = 0; i < 6; i++) ScrollingListItem(enabled: i != 0)
];
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("List"),
backgroundColor: Colors.green,
),
body: Center(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
RotatedBox(
quarterTurns: 1,
child: SizedBox(
height: 600,
width: 800,
child: ListWheelScrollView(
controller: controller,
itemExtent: 100,
physics: const FixedExtentScrollPhysics(),
onSelectedItemChanged: (idx) {
if (!children[idx].enabled) {
controller.animateToItem(
idx + 1,
duration: const Duration(milliseconds: 500),
curve: Curves.linear,
);
}
},
children: children,
),
),
),
const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
],
),
));
}
}
class ScrollingListItem extends StatelessWidget {
final bool enabled;
const ScrollingListItem({super.key, required this.enabled});
@override
Widget build(BuildContext context) {
return Container(
color: enabled ? Colors.green[200] : Colors.red[200],
height: 70,
width: 70,
alignment: Alignment.center,
child: RotatedBox(
quarterTurns: -1,
child: Text(
enabled ? "Enabled" : "Disabled",
),
),
);
}
}
It has a bug , the last element(extreme left container) will flash when List Wheel is moved to the disable element : -
The following code is similar to your provided solution but with little changes.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'List',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: const ScrollingList(),
);
}
}
class ScrollingList extends StatefulWidget {
const ScrollingList({Key? key}) : super(key: key);
@override
_ScrollingListState createState() => _ScrollingListState();
}
class _ScrollingListState extends State<ScrollingList> {
final controller = FixedExtentScrollController(initialItem: 1);
final children = [
for (int i = 0; i < 6; i++) ScrollingListItem(enabled: i != 0)
];
void scrollListener() {
if (controller.selectedItem == 1) {
if (controller.position.userScrollDirection == ScrollDirection.forward) {
controller.jumpToItem(1);
}
}
}
@override
void initState() {
super.initState();
controller.addListener(scrollListener);
}
@override
void dispose() {
controller.removeListener(scrollListener);
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("List"),
backgroundColor: Colors.green,
),
body: Center(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
RotatedBox(
quarterTurns: 1,
child: SizedBox(
height: 600,
width: 800,
child: ListWheelScrollView(
controller: controller,
itemExtent: 100,
physics: const FixedExtentScrollPhysics(),
// onSelectedItemChanged: (idx) {
// if (!children[idx].enabled) {
// controller.animateToItem(
// idx + 1,
// duration: const Duration(milliseconds: 500),
// curve: Curves.linear,
// );
// }
// },
children: children,
),
),
),
const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
],
),
));
}
}
class ScrollingListItem extends StatelessWidget {
final bool enabled;
const ScrollingListItem({super.key, required this.enabled});
@override
Widget build(BuildContext context) {
return Container(
color: enabled ? Colors.green[200] : Colors.red[200],
height: 70,
width: 70,
alignment: Alignment.center,
child: RotatedBox(
quarterTurns: -1,
child: Text(
enabled ? "Enabled" : "Disabled",
),
),
);
}
}
Hope it helps. Thanks :)