'How to create a constant looping auto-scroll in Flutter?
I am seeking to create a constant scroll of a dynamic number of images across my screen (similar to a news ticker) in Flutter. I want this to be automatic and a constant speed, that also loops.
The simplest solution I have found is to use the Carousel Package which ticks almost all the boxes, except one. I am unable to get a constant scroll speed
A possible solution was to adjust autoPlayInterval to zero, but unfortunately, this paramater appears to need a value of around 50 or greater to run - therefore creating an even scroll.
Any idea on how to tweak it this with this package? Or another suitable solution?
Simplified code:
@override
Widget build(BuildContext context) {
return Container(
child: CarouselSlider(
items: DynamicImages.list
.map(
(e) => Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset('assets/images/$e.png'),
),
)
.toList(),
options: CarouselOptions(
autoPlay: true,
autoPlayCurve: Curves.linear,
autoPlayInterval: Duration(milliseconds: 0), /// carousel will not run if set to zero
autoPlayAnimationDuration: Duration(milliseconds: 1000)
),
),
);
}
}
Solution 1:[1]
So, I've been working on this since posting and come up with a solution. I am posting my answer in case it helps any others in the future.
Basically, instead of using Carousel package, I used ListView.builder which then continuously grows as needed.
Of note, I needed to use WidgetsBinding.instance.addPostFrameCallback((timeStamp) {}); to get this to work.
It would still be great to see any other solutions, (as I am sure the below workaround could be improved).
import 'package:flutter/material.dart';
class ScrollLoop extends StatefulWidget {
const ScrollLoop({Key? key}) : super(key: key);
@override
_ScrollLoopState createState() => _ScrollLoopState();
}
class _ScrollLoopState extends State<ScrollLoop> {
ScrollController _controller = ScrollController();
/// [_list] is growable and holds the assets which will scroll.
List<String> _list = [
"assets/images/image1.png",
/// etc...
];
/// [_list2] holds duplicate data and is used to append to [_list].
List<String> _list2 = [];
/// [_listAppended] ensures [_list] is only appended once per cycle.
bool _listAppended = false;
@override
void initState() {
_list2.addAll(_list);
/// To auto-start the animation when the screen loads.
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
_startScroll();
});
/// The [_controller] will notify [_list] to be appended when the animation is near completion.
_controller.addListener(
() {
if (_controller.position.pixels >
_controller.position.maxScrollExtent * 0.90) {
if (_listAppended == false) {
_list.addAll(_list2);
_listAppended = true;
}
}
/// The [_controller] will listen for when the animation cycle completes,
/// so this can immediately re-start from the completed position.
if (_controller.position.pixels ==
_controller.position.maxScrollExtent) {
_listAppended = false;
setState(() {});
WidgetsBinding.instance!.addPostFrameCallback(
(timeStamp) {
_startScroll();
},
);
}
},
);
super.initState();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
}
void _startScroll() {
_controller.animateTo(_controller.position.maxScrollExtent,
duration: Duration(milliseconds: 8000), curve: Curves.linear);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final _size = MediaQuery.of(context).size;
return AbsorbPointer(
child: Material(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: ListView.builder(
shrinkWrap: true,
controller: _controller,
scrollDirection: Axis.horizontal,
itemCount: _list.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: _size.width / 4,
height: _size.height / 10,
child: Image.asset(_list[index]),
),
);
},
),
),
],
),
),
),
);
}
}
Solution 2:[2]
you're right about Carousel Package. You try this plugin scroll_loop_auto_scroll
This Plugin automatically scrolls the custom child widget to an infinite loop.
You can adjust, interval for every round, scroll position, Duration. and other stuff.
Other features
- Infinite Auto Scroll
- Custom child widgets
- Delay after every round
- Custom scroll direction
- Specifying custom durations and gap
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Kdon |
Solution 2 |