text_highlight_codespark 2.2.0
text_highlight_codespark: ^2.2.0 copied to clipboard
Flutter widget for highlighting rich text — single query, multiple queries with per-term colors, regex patterns, tappable spans, and rounded-corner styling.
text_highlight_codespark #
A Flutter widget for highlighting text — search terms, keywords, and regex patterns — with per-term colors, tappable spans, rounded corners, and full layout control.
Built by Katayath Sai Kiran · @Katayath-Sai-Kiran
Screenshots #
Features #
- Single query — highlight every occurrence of one search term
- Whole-word matching —
matchWordrestricts matches to word boundaries - Multiple queries — highlight several terms simultaneously, each with its own color
- Regex highlighting — match any pattern using standard Dart RegExp
- Per-term colors —
Map<String, Color>lets each keyword have a distinct background - Tappable highlights —
onTap/onTapIndexeddeliver the matched string (and index) on tap - Selectable text —
selectablerenders copyable text viaSelectableText.rich - Composable spans —
HighlightText.buildSpans()returns rawTextSpans for custom layouts - Rounded corners —
borderRadiusgives highlights a pill or badge look - Layout passthrough —
textAlign,maxLines,overflow,softWrap,textScaler,strutStyle, and more - Case-insensitive by default — opt into case-sensitive matching per widget
- Regex-safe multiple mode — special characters like
c++are escaped automatically
Installation #
Add to your pubspec.yaml:
dependencies:
text_highlight_codespark: ^2.2.0
Then run:
flutter pub get
Import in your Dart file:
import 'package:text_highlight_codespark/text_highlight_codespark.dart';
Usage #
Single query #
Highlight every occurrence of one search term:
HighlightText(
source: 'This is an example of Flutter text highlighting.',
highlight: HighlightQuery.single('example'),
highlightColor: Colors.yellow,
textStyle: TextStyle(fontSize: 16),
matchedTextStyle: TextStyle(fontWeight: FontWeight.bold),
)
Override the color for just this query:
HighlightText(
source: 'Flutter makes beautiful UIs.',
highlight: HighlightQuery.single('Flutter', color: Colors.blue.shade200),
)
Multiple queries with per-term colors #
Highlight several keywords at once, each in a different color:
HighlightText(
source: 'Flutter and Dart are great technologies for building apps.',
highlight: HighlightQuery.multiple(
['Flutter', 'Dart', 'apps'],
colors: {
'Flutter': Colors.blue.shade200,
'Dart': Colors.teal.shade200,
'apps': Colors.orange.shade200,
},
),
textStyle: TextStyle(fontSize: 16),
)
Special characters in query strings (e.g. c++, (text)) are escaped automatically and always match literally.
Regex highlighting #
Highlight any pattern supported by Dart's RegExp:
// Highlight 4-digit year numbers
HighlightText(
source: 'The years 2022, 2023, and 2024 are important.',
highlight: HighlightQuery.regex(r'\b\d{4}\b'),
highlightColor: Colors.purple.shade200,
matchedTextStyle: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
)
// Highlight email addresses
HighlightText(
source: 'Contact us at hello@example.com or support@example.com.',
highlight: HighlightQuery.regex(r'[\w.]+@[\w.]+\.\w+'),
highlightColor: Colors.green.shade200,
)
Tappable highlights #
Fire a callback with the matched string when the user taps a highlight:
HighlightText(
source: 'Tap any highlighted word to learn more about Flutter or Dart.',
highlight: HighlightQuery.multiple(['Flutter', 'Dart']),
highlightColor: Colors.amber.shade200,
onTap: (word) {
// word is the exact string the user tapped
showBottomSheet(...);
},
)
Rounded-corner highlights #
Give highlights a badge or pill appearance:
HighlightText(
source: 'Rounded highlights look modern and clean in Flutter UIs.',
highlight: HighlightQuery.single('highlights'),
highlightColor: Colors.green.shade300,
borderRadius: BorderRadius.circular(6),
matchedTextStyle: TextStyle(fontWeight: FontWeight.w600),
)
Whole-word matching #
Highlight whole words only — matchWord wraps queries in word boundaries, so dart matches dart but not dartboard:
HighlightText(
source: 'dart is great, dartboard is not.',
highlight: HighlightQuery.single('dart', matchWord: true),
highlightColor: Colors.green.shade200,
)
HighlightText(
source: 'State flows through widgets and state management.',
highlight: HighlightQuery.multiple(['state', 'flutter'], matchWord: true),
)
Selectable text #
Render copyable text with SelectableText.rich. Note that selection only works with plain text spans, so borderRadius (and onTap) are disabled in this mode:
HighlightText(
source: 'Select and copy this highlighted sentence.',
highlight: HighlightQuery.multiple(['Select', 'copy']),
selectable: true,
selectionColor: Colors.blue.withValues(alpha: 0.3),
)
Composable spans #
Build highlighted TextSpans without a widget, then embed them in your own text tree:
final spans = HighlightText.buildSpans(
source: 'RichText composes highlighted spans.',
highlight: HighlightQuery.multiple(['RichText', 'spans']),
);
Text.rich(TextSpan(children: spans));
Tapped match index #
Need to know which occurrence was tapped? Use onTapIndexed:
HighlightText(
source: 'red green red blue red',
highlight: HighlightQuery.single('red'),
onTapIndexed: (word, index) => print('Tapped #$index: $word'),
)
Layout control #
All standard Text layout parameters are supported:
HighlightText(
source: 'A very long string that might overflow on smaller screens in Flutter.',
highlight: HighlightQuery.single('Flutter'),
highlightColor: Colors.yellow,
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
softWrap: true,
)
API Reference #
HighlightText parameters #
| Parameter | Type | Default | Description |
|---|---|---|---|
source |
String |
required | The full text to display. |
highlight |
HighlightQuery |
required | What to highlight — .single, .multiple, or .regex. |
highlightColor |
Color |
Colors.yellow |
Fallback background color for matched spans. |
textStyle |
TextStyle? |
null |
Style for the entire source text. |
matchedTextStyle |
TextStyle? |
null |
Extra style merged onto matched spans (backgroundColor ignored). |
caseSensitive |
bool |
false |
Whether matching is case-sensitive. |
onTap |
void Function(String)? |
null |
Callback fired with the matched text on tap. |
onTapIndexed |
void Function(String, int)? |
null |
Like onTap but also delivers the 0-based match index. |
borderRadius |
BorderRadius? |
null |
Rounds the corners of matched spans. |
selectable |
bool |
false |
Renders copyable text via SelectableText.rich. |
textAlign |
TextAlign? |
null |
Text alignment — passed to the text widget. |
maxLines |
int? |
null |
Max line count — passed to the text widget. |
overflow |
TextOverflow? |
null |
Overflow behavior — passed to Text.rich. |
softWrap |
bool? |
null |
Soft wrap — passed to Text.rich. |
strutStyle |
StrutStyle? |
null |
Strut style — passed to the text widget. |
textDirection |
TextDirection? |
null |
Text direction — passed to the text widget. |
locale |
Locale? |
null |
Locale — passed to Text.rich. |
textScaler |
TextScaler? |
null |
Text scaler — passed to the text widget. |
textWidthBasis |
TextWidthBasis? |
null |
Text width basis — passed to the text widget. |
textHeightBehavior |
TextHeightBehavior? |
null |
Text height behavior — passed to the text widget. |
selectionColor |
Color? |
null |
Selection color when selectable is true. |
semanticsLabel |
String? |
null |
Semantic label — passed to the text widget. |
HighlightQuery constructors #
| Constructor | Parameters | Description |
|---|---|---|
HighlightQuery.single(query, {color, matchWord}) |
String, optional Color, optional bool |
Highlight one term, optionally whole words only. |
HighlightQuery.multiple(queries, {colors, matchWord}) |
List<String>, optional Map<String, Color>, optional bool |
Highlight multiple terms with optional per-term colors. |
HighlightQuery.regex(pattern) |
String |
Highlight all regex matches. |
Limitations #
- Selection + rounded corners —
WidgetSpan-based highlights (borderRadius) can't be selected; useselectable: true(plain spans only) when copyable text matters. - Whole-word boundaries —
matchWorduses Dart's\b, which treats only[A-Za-z0-9_]as word characters; non-ASCII words won't boundary-match. - Overlapping queries —
.multiplematches longest-first, so'highlight text'wins over'text'inside that phrase.
Migration from 1.x #
Version 2.0 replaced the three constructors (HighlightText, HighlightText.multiple, HighlightText.regex) with a single HighlightText widget plus HighlightQuery. Migrate by passing the query object:
// 1.x
HighlightText('text', query: 'example');
// 2.x
HighlightText(source: 'text', highlight: HighlightQuery.single('example'));
Contributing #
See CONTRIBUTING.md for guidelines, and open an issue for bugs or feature requests.
