How to make a Text widget act like marquee when the text overflows in Flutter

10,316

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,
)

enter image description here

Share:
10,316
Jaswant Singh
Author by

Jaswant Singh

Ping me at [email protected]

Updated on June 05, 2022

Comments

  • Jaswant Singh
    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
    Vettiyanakan over 4 years
    '_positions.isNotEmpty': ScrollController not attached to any scroll views. Showing this error on exiting a page with this widget.
  • leodriesch
    leodriesch over 4 years
    Is 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
    rohan koshti almost 4 years
    Saved many hours for me... and did not want to use any package. This works 100% ..
  • Priya Sindkar
    Priya Sindkar about 3 years
    Simple 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
    Kamlesh almost 3 years
    @leodriesch Kindly update it as per NULL SAFETY. Thanks a lot :)
  • Emmanuel Njorodongo
    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
    leodriesch over 2 years
    I 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
    Alok Kumar almost 2 years
    Can you give an example