Search code examples
flutterdarttextflutter-animation

Flutter: animate text color


I am trying to animate some text in my flutter app so that each word's color changes, one after the other - kind of like in karaoke:

I've been looking at packages like animated_text_kit but so far have not found a ready-made solution for this. Maybe there is one out there?

If not, how might I go about making this animation? Making a custom animation for animated_text_kit maybe?

Ideally the amount of time each word is highlighted would depend on the length of the word, too.

Edit: here is what I am trying so far - not the intended effect though.

  Widget textAnimated() {
    TextStyle style = TextStyle(
        fontSize: 18,
        height: 3.0,
    return Padding(
        padding: const EdgeInsets.only(left: 10, right: 10, top: 140),
        child: AnimatedTextKit(
          animatedTexts: [
            ColorizeAnimatedText("The quick brown fox jumps over the lazy dog.",
                textStyle: style, colors: [Colors.white, Colors.black])
          ],
        ));
  }

Solution

  • You can use this widget

      MyAnimatedText(
                sentence: "The quick brown fox jumps over the lazy dog.",
              )
    

    MyAnimatedText widget

    class MyAnimatedText extends StatefulWidget {
      final String sentence;
    
      const MyAnimatedText({
        Key? key,
        required this.sentence,
      }) : super(key: key);
    
      @override
      State<MyAnimatedText> createState() => _MyAnimatedTextState();
    }
    
    class _MyAnimatedTextState extends State<MyAnimatedText> {
      late List<String> words = widget.sentence.split(" ").toList();
    
      late Timer timer;
    
      int activeIndex = 0;
    
      @override
      void initState() {
        super.initState();
    
        timer = Timer.periodic(const Duration(seconds: 1), (timer) {
          activeIndex++;
          if (activeIndex > words.length) activeIndex = 0;
          setState(() {});
        });
      }
    
      @override
      void dispose() {
        timer.cancel();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return RichText(
          text: TextSpan(
            children: () {
              List<InlineSpan> spans = [];
              for (int i = 0; i < words.length; i++) {
                spans.add(TextSpan(
                  text: words[i] + " ",
                  style: i == activeIndex
                      ? const TextStyle( //highlight style
                          color: Colors.orange,
                          fontSize: 24,
                        )
                      : TextStyle(
                          color: Colors.grey.shade300,
                          fontSize: 24,
                        ),
                ));
              }
              return spans;
            }(),
          ),
        );
      }
    }