Animate specific part of txt?By RichText in Flutter, I changed background color by tween animation How to do brush stroke type animation on highlight

Viewed 211

I want to make an Epub Reader with text highlighting, text selections. But I tried using RichText and highlight_text package. But it is static and does not add highlighting animations. Like I want to show the highlight happening (brush stroke from right to left on a word). In Flutter, is there any way to do it? I want to add animations to each text highlight:

`TextHighlight(
            //This widget uses RichText and nested TextSpan for highlighting
            //I want to add animations to the text Inside TextSpan
            text: text,
            words: words as LinkedHashMap<String, HighlightedWord>,
            textStyle: TextStyle(
              fontSize: 20.0,
              color: Colors.black,
              backgroundColor: Colors.transparent,
            ),`

Flutter package I am using highlight_text ``

library highlight_text;

import 'dart:collection';
import 'dart:core';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

class HighlightedWord {
  final TextStyle textStyle;
  final VoidCallback onTap;

  HighlightedWord({
    required this.onTap,
    required this.textStyle,
  });
}

class TextHighlight extends StatefulWidget {
  String text;
   TextAlign textAlign;
   TextDirection? textDirection;
   bool softWrap;
   TextOverflow overflow;
   double textScaleFactor;
   int? maxLines;
   Locale? locale;
   StrutStyle? strutStyle;
   bool enableCaseSensitive;
  TextHighlight({
    required this.text,
    required this.words,
    this.textStyle = const TextStyle(
      fontSize: 25.0,
      color: Colors.black,
    ),
    this.textAlign = TextAlign.start,
    this.textDirection,
    this.softWrap = true,
    this.overflow = TextOverflow.clip,
    this.textScaleFactor = 1.0,
    this.maxLines,
    this.locale,
    this.strutStyle,
    this.enableCaseSensitive = false,
  }); 

  @override
  _TextHightlightState createState() => _TextHighlightState(
    required this.text,
    required this.words,
    this.textStyle = const TextStyle(
      fontSize: 25.0,
      color: Colors.black,
    ),
    this.textAlign = TextAlign.start,
    this.textDirection,
    this.softWrap = true,
    this.overflow = TextOverflow.clip,
    this.textScaleFactor = 1.0,
    this.maxLines,
    this.locale,
    this.strutStyle,
    this.enableCaseSensitive = false,
  );
}

class _TextHighlightState extends State<TextHighlight> {
  String text;
   TextAlign textAlign;
   TextDirection? textDirection;
   bool softWrap;
   TextOverflow overflow;
   double textScaleFactor;
   int? maxLines;
   Locale? locale;
   StrutStyle? strutStyle;
   bool enableCaseSensitive;
  @override
  void initState(){
    text = widget.text;
    textAlign = widget.textAlign;
    
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    List<String> _textWords = _bind();

    return AnimatedDefaultTextStyle(
      child: RichText(
        text: _buildSpan(_textWords),
        locale: locale,
        maxLines: maxLines,
        overflow: overflow,
        softWrap: softWrap,
        strutStyle: strutStyle,
        textAlign: textAlign,
        textDirection: textDirection,
        textScaleFactor: textScaleFactor,
      ),
    );
  }

  List<String> _bind() {
    String bindedText = text;
    for (String word in words.keys) {
      if (enableCaseSensitive) {
        bindedText = bindedText.replaceAll(
            word, '<highlight>${words.keys.toList().indexOf(word)}<highlight>');
      } else {
        int strIndex = bindedText.toLowerCase().indexOf(word.toLowerCase());
        print('$word\n');
        bindedText = bindedText.replaceRange(strIndex, strIndex + word.length,
            '<highlight>${words.keys.toList().indexOf(word)}<highlight>');
      }
    }

    List<String> splitedTexts = bindedText.split("<highlight>");
    splitedTexts.removeWhere((s) => s.isEmpty);

    return splitedTexts;
  }

  TextSpan _buildSpan(List<String> bindedWords) {
    if (bindedWords.isEmpty) return TextSpan();

    String nextToDisplay = bindedWords.first;
    bindedWords.removeAt(0);

    int? index = int.tryParse(nextToDisplay);

    if (index != null) {
      String currentWord = words.keys.toList()[index];
      return TextSpan(
        text: currentWord,
        style: words[currentWord]!.textStyle,
        children: [
          _buildSpan(bindedWords),
        ],
        recognizer: TapGestureRecognizer()
          ..onTap = () => words[currentWord]!.onTap(),
      );
    }

    return TextSpan(
      text: nextToDisplay,
      style: textStyle,
      children: [
        _buildSpan(bindedWords),
      ],
    );
  }
}

Is there any way to do animations, tweaking the package code in some way.. or any other workaround.. Baiscally I want to highlight a specific text, rendered by Text widget. In mobile and Web.

0 Answers
Related