Giter Site home page Giter Site logo

highlight_text's Introduction

Highlight Text Plugin

A flutter package to highlight words from a text.

Usage

To use this package, add highlight_text as a dependency in your pubspec.yaml file.

Getting Started

With this package you can highlight words and create specific actions for each highlighted word, you can customize the style of each word separately or create a unique style for all of them, you can also customize the style of the rest of the text.

Example

Import the highlight library

import 'package:highlight_text/highlight_text.dart';

You should use the HighlightedWord class to specify the dictionary words in a Map object

Map<String, HighlightedWord> words = {
    "Flutter": HighlightedWord(
        onTap: () {
            print("Flutter");
        },
        textStyle: textStyle,
    ),
    "open-source": HighlightedWord(
        onTap: () {
            print("open-source");
        },
        textStyle: textStyle,
    ),
    "Android": HighlightedWord(
        onTap: () {
            print("Android");
        },
        textStyle: textStyle,
    ),
};

Now you can call the TextHighlight widget

TextHighlight(
    text: text, // You need to pass the string you want the highlights
    words: words, // Your dictionary words
    textStyle: TextStyle( // You can set the general style, like a Text()
        fontSize: 20.0,
        color: Colors.black,
    ),
    textAlign: TextAlign.justify, // You can use any attribute of the RichText widget
),

Package example image

1.1.0 Update

Now you can customize better the words you highlight, just like a Container. It was added decoration and padding fields to HighlightedWord object, so you can do whatever you want to customize it.

HighlightedWord(
    onTap: () {},
    textStyle: textStyle,
    decoration: BoxDecoration(
        color: Colors.green,
        borderRadius: BorderRadius.circular(50),
    ),
    padding: EdgeInsets.all(8.0),
),

1.2.0 Breaking changes

enableCaseSensitive renamed to matchCase to be clearer about what it does

TextHighlight(
    text: text,
    words: words,
    matchCase: true // will highlight only exactly the same string
),

highlight_text's People

Contributors

crizant avatar desconexo avatar hakob avatar petermusembi69 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

highlight_text's Issues

First word in text not matching

it's not matching for first word in text
Screen Shot 2021-09-01 at 4 32 38 PM
. I believe the error is caused by the statement in line 80 in highlight_text.dart. strIndex should be compared to ">= 0"

if (strIndex > 0)
bindedText = bindedText.replaceRange(strIndex, strIndex + word.length,
'${words.keys.toList().indexOf(word)}');

RangeError (index): Invalid value: Valid value range is empty: -1

Having a space at the end of the string ( for example "This is a string " ) throws RangeError (index): Invalid value: Valid value range is empty: -1. Removing the space ( for example "This is a string" ) fixes the problem. There might be a problem in the way string is parsed

Unexpected highlighting behavior

Code:

 _tags  = ['pokemon', 'pokemon-trainer'];
    return Map.fromIterable(test,
        key: (k) => k,
        value: (k) => HighlightedWord(
            textStyle: TextStyle(
              color: LucidPurple,
              fontSize: 15,
              wordSpacing: 1.4,
              height: 1.5,
            ),
            onTap: () {}));
            
            
 TextHighlight(
          text: 'what up what up pokemon pokemon-trainer',
          words: _tags,
          textStyle: TextStyle(
            color: LucidWhite,
            fontSize: 15,
            wordSpacing: 1.4,
            height: 1.5,
          ),
        )

Expected behavior:
'what up what up pokemon pokemon-trainer'

Actual behavior:
what up what up pokemon pokemon-trainer

Highlighting URLs using highlight_text package based on some logic

I'm developing a mobile application in flutter. It needs to highlight some urls present in a string based on some logic. I find highlight_text package to do the task. This takes text and words that is to be highlighted. Everything is working fine except when i'm passing text that contains url followed by some number. It is throwing error as following:

Another exception was thrown: RangeError (index): Invalid value: Only valid value is 0: 6777
text : In a meeting, will call you later. On my wa'y Please call me later www.something.in 6777
word : www.something.in

But when url is followed by some number and then by some text, it does not throw exception and works well.

text : In a meeting, will call you later. On my way Please call me later www.something.in 6777 test text

word : www.something.in

here is my code snippet

Map<String, bool> textContent = {'www.something1.in': true,'www.something2.in': false};
                        Map<String, HighlightedWord> words = {};
                         textContent.forEach((key, value) {
                              if (value) {
                                words[key] = HighlightedWord(
                                  onTap: () {
                                    debugPrint(key);
                                  },
                                  textStyle: const TextStyle(
                                      decoration: TextDecoration.underline,
                                      color: Colors.red,
                                      fontSize: 13,
                                      fontWeight: FontWeight.bold),
                                );
                                imageURL = 'images/mal.png';
                              } else {
                                words[key] = HighlightedWord(
                                  onTap: () {
                                    debugPrint(key);
                                  },
                                  textStyle: const TextStyle(
                                      decoration: TextDecoration.underline,
                                      color: Colors.blue,
                                      fontSize: 13),
                                );
                              }
                            });  

Above code snippets preparing words that is to be highlighted.

TextHighlight(
                      text: text,
                      words: words,
                      maxLines: 3,
                      textStyle: const TextStyle(
                        fontSize: 13.5,
                        overflow: TextOverflow.clip,
                        color: Colors.black,
                      ),
                    ),

This is where i am passing text and words. Exception is throwing at line with keyword TextHighlight. There are text of
exception

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ The following RangeError was thrown building TextHighlight(dirty): RangeError (index): Invalid value: Only valid value is 0: 6777

Can someone please tell me what's the issue with my code? I have exhausted debugging it. It’ll be great help.

Empty text cause error

Hi, thank you for this package.
I try to use this package. I found an error.
If currentWord is empty, that line cause error.

String charLastRemoved = currentWord[currentWord.length - 1];

No Screenshots!

Its such a visual Plgin why are there no screenshots. I (and probably many more) want to see how it looks before i install a Plugin like that

Background and backgroundColor does not work as expected

Problematic Widget: HighlightedWord

If I use a text:

"I had some aggression then
In the airport someone was there"

If I give a map of HighlightedWord with TextStyle including:

backgroundColor: Colors.red
or
background: Paint()
..strokeWidth = 10.0
..color = Colors.red
..style = PaintingStyle.stroke
..strokeJoin = StrokeJoin.round

What I expect to see is the only the background of my keys should be red.

But my background starts from the first key, ends at the end of the text.

matchCase not working if false

Text not matching pattern by case is not highlighted.

In highlight_text.dart, line 96, loop condition contains word.allMatches(text).length, which is case-sensitive.

Improve Null exception handling

This code region could potentially be null, hence resulting in a Exception, hence a better null handling flow is required as opposed to only using a try catch block.

In my personal opinion, inorder to assist developers in having a smooth time debugging where they watch out for all thrown exceptions, I think it is not convinient to only wrap try catch in regions where we are sure of a potential null error, especially in open source libraries.

      int? index = int.tryParse(nextToDisplay);
     try {
        String currentWord = words.keys.toList()[index!];

Support SelectionArea

When we wrap SelectionArea around a widget tree, all Text widgets in this widget tree are selectable.
But the RichText widget used by this package needs some modification:

e.g.

RichText(
  // ...
  selectionRegistrar: SelectionContainer.maybeOf(context),
  selectionColor: Theme.of(context).textSelectionTheme.selectionColor ?? const Color(0xAF6694e8),
)

Source: https://api.flutter.dev/flutter/widgets/RichText-class.html

Performance really slow.

I used in ListView about 6-10 item which has a TextHighlight on Web.
and restart App just stuck. after change to default text widget, works on..

  return GestureDetector(
      onTap: onTap,
      child: Card(
        clipBehavior: Clip.hardEdge,
        child: Column(
          children: [
            WebImage(
              post.thumbnail,
              width: 700,
              height: 350,
              fit: ObjectFit.cover,
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(post.title), // this part change to TextHightlight
                  Text(
                    DateFormat("yyyy년MM월dd일").format(post.releaseDateTime),
                  ),
                  Row(
                    children: post.tagList.map((e) => Text("#$e ")).toList(),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );

Am i used wrong way?

Highlight not showing on overflowed text

Hi, I have some app that has UI like this.
highlight text

The problem is, the highlighted part won't show on overflowed text. My code probably something like this.

TextHighlight(
    text: 'Aditya Putra Pratama',
    words: {
        'pratama': HighlightedWord(
          decoration: BoxDecoration(
            color: Colours.yellow,
            borderRadius: BorderRadius.circular(3),
          ),
          padding: EdgeInsets.symmetric(horizontal: 2),
        ),
    },
    maxLines: 1,
    overflow: TextOverflow.ellipsis,
    textAlign: TextAlign.center,
)

ignore capital letters

are capital letters ignored? if not, is it possible to add the corresponding flag to the parameters to ignore them

How to ignore case put paint original world

Hi,

I want paint all words, ignoring case, but without change the "original word".

Im highlight word "JeSuS", but when i use "enableCaseSensitive: false" it highlight the word changing their original case too.

Im searching for "JeSuS" and it change original words "JESUS" and "Jesus" for "JeSuS" too.

image

Can you make some variable to keep original case and only highlight the word?

Thanks.

Single number as HighlightedWord causes error

This is a very useful package. Thank you for creating it!
I faced some issues in my work with it and I found work around, but since it might be useful for other users, I decided to document it.
To present overview of evaluation, I need to replace some substrings in a template message and to print them out with additional styling. For this task I use combination of ARB file and this package. All values are loading from API and I may receive null for some of them. Here are two issues I faced in my work:

  1. with nullable keys:
    I save nullable variables like this
    final value = data?.toString() ?? '';
    and it doesn't return compile error, but causes an ugly result.
    Fix this with adding it with if statement - if(data != null) template: HighlightedWord(textStyle:...),

  2. with single numbers:
    If some of keys is number (like 0) it replaces substrings, witch have their own different key.
    Example: "0's points didn't change. Current number of points is 0. 0 has changed technical seniority to Intern."
    where replaced values are bold and instead of userName: HighlightedWord(textStyle:...), for customizing that value is used score: HighlightedWord(textStyle:...) where score = scoreValue.toString() and scoreValue = 0
    Fix this with with adding empty space in front of the number character like this: score = ' ${scoreValue.toString()}'

Hopefully this information will be useful to others. And again: Thank you for creating this package!

Not working with numbers

String needle = '22020 toy 4x4 combo';

String haystack = '17801-22020 TOY RAV4 COMBO 4x4';

List<String> needleList = needle.split(' ');

Map<String, HighlightedWord> testWords = {
  for (var v in needleList)
    v: HighlightedWord(
        textStyle: TextStyle(color: Colors.red), onTap: () {})
};

the 22020 does not get highlighted sadly Is this a limitation? :(

edit: 17801-22020 (works), -22020 (does not work), rav (works), so this is more like a limitation of IF it contains numbers then it needs to match the entire word?

matchCase: true will through an error

Hi there!

When I set matchCase to true, I get the following error:

highlight_text dart — carpediem 2022-09-23 14-23-45

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.3.2, on macOS 12.6 21G115 darwin-x64, locale en-DE)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc2)
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
[✓] Android Studio (version 2021.2)
[✓] IntelliJ IDEA Community Edition (version 2021.2.3)
[✓] VS Code (version 1.71.2)
[✓] Connected device (1 available)
[✓] HTTP Host Availability

Has anyone ever faced this?

I am on version highlight_text: ^1.4.1

Thanks!

Support `|` character and numbers

Currently if the user input contains two | characters around a number, the output may be incorrect.
i.e.: the | characters will be removed and the numbers may be replaced by highlight words.
I have a plan of solving this issue in two steps:

  1. Refactor the _buildSpan() method to remove the recursion.
  2. Make the _bind() method returns a List of String and int values, then we can tell if it's an int, it is a word that should be highlighted.

Multiple Highlight

I'm trying to highlight one specific occurrence of a word and it highlighting it where it shows up in the text.

eg.
"This is an sad day. I want an icecream and sauce."

Should I do this it will highlight this when I only wanted the second an.

onTap should not be required

Since some developers only want a special substring to be highlighted instead of making it clickable, I think the onTap callback should be optional / not required by default.

last word in string

If the highlighted word is the last in the string it is not highlighted.
example:
word word word word word

:bulb: onPressed should be optional

Hi! 👋 First of all: Great package! Helped me to highlight more than one word without the need of nesting the same widget over and over again like I have to with other packages. 👍
Nevertheless I think the onPressed parameter should be optional, because in most of the use cases, the developer only wants to highlight text.

RangeError

Lines 74,75 in highlight_text.dart,

 int strIndex = bindedText.toLowerCase().indexOf(word.toLowerCase());
 bindedText = bindedText.replaceRange(strIndex, strIndex + word.length,
            '<highlight>${words.keys.toList().indexOf(word)}<highlight>');

throws an instance of 'RangeError' when the 'word.toLowerCase()' is not found in 'bindedText.toLowerCase()' whereby 'strIndex' is set to -1. A condition is missing here?

int strIndex = bindedText.toLowerCase().indexOf(word.toLowerCase());
if(strIndex>=0) {
 bindedText = bindedText.replaceRange(strIndex, strIndex + word.length,
            '<highlight>${words.keys.toList().indexOf(word)}<highlight>');
}

RangeError (index): Invalid value: Valid value range is empty: 0

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following RangeError was thrown building TextHighlight(dirty, state: _TextHighlightState#140ef):
RangeError (index): Invalid value: Valid value range is empty: 0
When the exception was thrown, this was the stack:
#0 List.[] (dart:core-patch/growable_array.dart:145:60)
#1 _TextHighlightState.build (package:highlight_text/src/TextHighlight.dart:51:34)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:3825:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3739:15)
#4 Element.rebuild (package:flutter/src/widgets/framework.dart:3565:5)
#5 StatefulElement.update (package:flutter/src/widgets/framework.dart:3894:5)
#6 Element.updateChild (package:flutter/src/widgets/framework.dart:2753:15)

exception when move back on page with TextHighlight

my solve
image

First word in text is raised

If the first word in the text is marked for highlighting, it is raised above the level of the following text. The only way I have found to partially resolve this is to add a " " before the text, but that causes a problem for left-aligning it. For example:

TextHighlight(
                text: "Testing the height of the first word", 
                words: highlightedWords as LinkedHashMap<String, HighlightedWord>,
                textStyle: TextStyle(
                    fontFamily: chosenFont,
                    color: color,
                    fontSize: fontSize,
                ),
                textAlign: TextAlign.left,
              )

highlightedWords = {};
String wordToAdd = "testing";

highlightedWords[wordToAdd] =
          HighlightedWord(
              onTap: () {
                setState(() {
                  action;
                });
              },
              textStyle: highlightTextStyle,
              decoration: highlightDecoration
          );

Results in:
Screenshot 2021-10-11 at 16 03 07

As you can see, I'm also having trouble with the matchCase: false setting too, but that's a different issue.

Thanks for making this by the way. I'm finding it useful!

Not working with Vietnamese

I tried:

TextStyle textStyle = TextStyle(
          color: prefix0.orangeColor,
          fontFamily: 'Roboto-Regular',
          fontSize: ScreenUtil().setSp(45.0));
      Map<String, HighlightedWord> words = Map();
      widget.message.messageActionsModel.mentions.mentions?.forEach((user) {
        words["@all"] =
            HighlightedWord(onTap: () {}, textStyle: textStyle);
      });
      HighlightMap highlightMap = HighlightMap(words);
      return TextHighlight(
        text: widget.message.messageActionsModel.msg,
        // You need to pass the string you want the highlights
        words: highlightMap.getMap,
        // Your dictionary words
        textStyle: TextStyle(
            color: widget.isOwner ? prefix0.white : prefix0.blackColor333,
            fontFamily: 'Roboto-Regular',
            fontSize: ScreenUtil().setSp(45.0)),
        textAlign:
            TextAlign.start, // You can use any attribute of the RichText widget
      );

=> It's working fine.
But if i use:

TextStyle textStyle = TextStyle(
          color: prefix0.orangeColor,
          fontFamily: 'Roboto-Regular',
          fontSize: ScreenUtil().setSp(45.0));
      Map<String, HighlightedWord> words = Map();
      widget.message.messageActionsModel.mentions.mentions?.forEach((user) {
        words["Nguyễn Hữu Bình"] =
            HighlightedWord(onTap: () {}, textStyle: textStyle);
      });
      HighlightMap highlightMap = HighlightMap(words);
      return TextHighlight(
        text: widget.message.messageActionsModel.msg,
        // You need to pass the string you want the highlights
        words: highlightMap.getMap,
        // Your dictionary words
        textStyle: TextStyle(
            color: widget.isOwner ? prefix0.white : prefix0.blackColor333,
            fontFamily: 'Roboto-Regular',
            fontSize: ScreenUtil().setSp(45.0)),
        textAlign:
            TextAlign.start, // You can use any attribute of the RichText widget
      );

=> It's not working for me.
Flutter doctor -v:
Screen Shot 2020-05-10 at 23 17 31

It doesn't work

  1. It doesn't work
List<String> groupList = matches.map((reg) => reg.group(0)).toList();
      Map<String, HighlightedWord> words = {};
       groupList.forEach((element) {
         words.putIfAbsent(
           element,
               () => HighlightedWord(
             onTap: () {
              print(element);
             },
             textStyle: TextStyle(color: Colors.red),
           ),
         );
       });
return TextHighlight(
        text: widget.text,
        words: words,
        textStyle: TextStyle(fontWeight: FontWeight.w500, color: Colors.black),
        textAlign: TextAlign.justify,
      );
  1. It works
      Map<String, HighlightedWord> words = {};
      words.putIfAbsent(
          "@hd-ui",
          () => HighlightedWord(
                onTap: () {
                  print("@hd-ui");
                },
                textStyle: TextStyle(color: Colors.red),
              ));
      words.putIfAbsent(
          "@hn-ui",
          () => HighlightedWord(
                onTap: () {
                  print("@hn-ui");
                },
                textStyle: TextStyle(color: Colors.red),
              ));
return TextHighlight(
        text: widget.text,
        words: words,
        textStyle: TextStyle(fontWeight: FontWeight.w500, color: Colors.black),
        textAlign: TextAlign.justify,
      );

Null safety

This is a request to add support for null safety to this package. See the migration guide for details about enabling null safety.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.