How to make a Text widget act like marquee when the text overflows in Flutter
Solution 1
This widget is what I came up with, and I think it serves your needs:
class MarqueeWidget extends StatefulWidget {
final Widget child;
final Axis direction;
final Duration animationDuration, backDuration, pauseDuration;
const MarqueeWidget({
Key? key,
required this.child,
this.direction = Axis.horizontal,
this.animationDuration = const Duration(milliseconds: 6000),
this.backDuration = const Duration(milliseconds: 800),
this.pauseDuration = const Duration(milliseconds: 800),
}) : super(key: key);
@override
_MarqueeWidgetState createState() => _MarqueeWidgetState();
}
class _MarqueeWidgetState extends State<MarqueeWidget> {
late ScrollController scrollController;
@override
void initState() {
scrollController = ScrollController(initialScrollOffset: 50.0);
WidgetsBinding.instance!.addPostFrameCallback(scroll);
super.initState();
}
@override
void dispose() {
scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: widget.child,
scrollDirection: widget.direction,
controller: scrollController,
);
}
void scroll(_) async {
while (scrollController.hasClients) {
await Future.delayed(widget.pauseDuration);
if (scrollController.hasClients) {
await scrollController.animateTo(
scrollController.position.maxScrollExtent,
duration: widget.animationDuration,
curve: Curves.ease,
);
}
await Future.delayed(widget.pauseDuration);
if (scrollController.hasClients) {
await scrollController.animateTo(
0.0,
duration: widget.backDuration,
curve: Curves.easeOut,
);
}
}
}
}
Its functionality should be pretty obvious. An example implementation would look like this:
class FlutterMarqueeText extends StatefulWidget {
const FlutterMarqueeText({Key? key}) : super(key: key);
@override
_FlutterMarqueeTextState createState() => _FlutterMarqueeTextState();
}
class _FlutterMarqueeTextState extends State<FlutterMarqueeText> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter Marquee Text"),
),
body: const Center(
child: SizedBox(
width: 200.0,
child: MarqueeWidget(
direction: Axis.horizontal,
child: Text("This text is to long to be shown in just one line"),
),
),
),
);
}
}
Solution 2
You can do it using a marquee package
marquee
widget that scrolls text infinitely. Provides many customizations including custom scroll directions, durations, curves as well as pauses after every round.
to use added marquee
dependencies in the pubspec.yaml file
dependencies:
marquee: ^2.1.0
To import the dependency to your file, use the following line of code:
import 'package:marquee/marquee.dart';
You can use it like this and this is simple without any parameter property
Marquee(
text: 'There once was a boy who told this story about a boy',
)
And you can also be using some properties and customizability like below
Marquee(
text: 'Some sample text that takes some space.',
style: TextStyle(fontWeight: FontWeight.bold),
scrollAxis: Axis.horizontal,
crossAxisAlignment: CrossAxisAlignment.start,
blankSpace: 20.0,
velocity: 100.0,
pauseAfterRound: Duration(seconds: 1),
startPadding: 10.0,
accelerationDuration: Duration(seconds: 1),
accelerationCurve: Curves.linear,
decelerationDuration: Duration(milliseconds: 500),
decelerationCurve: Curves.easeOut,
)
Comments
-
Jaswant Singh almost 2 years
I'm looking for a way to implement Marquee style on a Text widget so that it automatically start scrolling when the text is overflowed from the screen. Is there a way to do it. I've tried all the decoration modes but cant seem to find a Marquee option there.
-
Vettiyanakan over 4 years'_positions.isNotEmpty': ScrollController not attached to any scroll views. Showing this error on exiting a page with this widget.
-
leodriesch over 4 yearsIs the MarqueeWidget inside of a scrolling container like ListView? That might crash it, because it is not rendered yet, so the ScrollController isn't attached yet.
-
rohan koshti almost 4 yearsSaved many hours for me... and did not want to use any package. This works 100% ..
-
Priya Sindkar about 3 yearsSimple and elegant. I wanted to abruptly shift cursor to the last typed digit, so I replaced animateTo() with jumpTo() and removed the animation durations. Works great.
-
Kamlesh almost 3 years@leodriesch Kindly update it as per NULL SAFETY. Thanks a lot :)
-
Emmanuel Njorodongo over 2 years@leodriesch can you make the marquee to be continuous so that it does not pause and start again, you can make the words to that were on left to start coming from right
-
leodriesch over 2 yearsI don’t really do any Flutter anymore, so unfortunately I can’t. You could try yourself or ask another question here with my code in it and ask someone else to modify it.
-
Alok Kumar almost 2 yearsCan you give an example