rich_text_controllerx 1.1.0
rich_text_controllerx: ^1.1.0 copied to clipboard
An extended text editing controller that supports different inline styles for custom regex patterns
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:rich_text_controllerx/rich_text_controllerx.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<StatefulWidget> createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
bool enableHighlight = true;
bool enableOnTapInto = true;
bool enableOnSelected = true;
MatchResultItem? matchTappedItem;
void _onWordMatchTap(MatchResultItem tappedItem) =>
setState(() => matchTappedItem = tappedItem);
late final RichTextController controller = RichTextController(
text:
'Home sweet home! Do good homework and housework at home. The happyness of an ending.',
sortTargetsByPatternLength: true,
mergeOverlappingStyles: true,
deleteOnBack: true,
enableHighlight: true,
enableOnTapInto: true,
enableOnSelected: true,
onMatch: (List<MatchResultItem> matches) {
for (final MatchResultItem match in matches) {
log(match.toString());
}
},
targets: [
// --------------------------------------------------------------
// SINGLE STRING
// --------------------------------------------------------------
MatchTargetItem.string(
'homework',
style:
const TextStyle(color: Colors.orange, fontWeight: FontWeight.bold),
stringMatch: StringMatch.exact,
caseSensitive: false,
onSelected: (MatchResultItem match) => _onWordMatchTap(match),
onTapInto: (MatchResultItem match) => _onWordMatchTap(match),
),
MatchTargetItem.string(
'Home',
style: const TextStyle(color: Colors.red),
stringMatch: StringMatch.any,
caseSensitive: false,
onSelected: (MatchResultItem match) => _onWordMatchTap(match),
onTapInto: (MatchResultItem match) => _onWordMatchTap(match),
),
// Prefix
MatchTargetItem.string(
'happy',
style: const TextStyle(color: Colors.blue),
stringMatch: StringMatch.prefix,
caseSensitive: false,
onSelected: (MatchResultItem match) => _onWordMatchTap(match),
onTapInto: (MatchResultItem match) => _onWordMatchTap(match),
),
// Postfix
MatchTargetItem.string(
'ing',
style: const TextStyle(color: Colors.blue),
stringMatch: StringMatch.postfix,
caseSensitive: false,
onSelected: (MatchResultItem match) => _onWordMatchTap(match),
onTapInto: (MatchResultItem match) => _onWordMatchTap(match),
),
// --------------------------------------------------------------
// MULTIPLE STRINGS
// --------------------------------------------------------------
MatchTargetItem.strings(
['do', 'at'],
style: const TextStyle(color: Colors.pink),
onSelected: (MatchResultItem match) => _onWordMatchTap(match),
onTapInto: (MatchResultItem match) => _onWordMatchTap(match),
),
// --------------------------------------------------------------
// SINGLE REGEXP
// --------------------------------------------------------------
MatchTargetItem.regex(
RegExp(r'sweet'),
style: const TextStyle(color: Colors.indigo),
onSelected: (MatchResultItem match) => _onWordMatchTap(match),
onTapInto: (MatchResultItem match) => _onWordMatchTap(match),
),
// --------------------------------------------------------------
// MUTIPLE REGEXPs
// --------------------------------------------------------------
MatchTargetItem.regexes(
[RegExp(r'good'), RegExp(r'and')],
style: const TextStyle(
decoration: TextDecoration.underline,
decorationStyle: TextDecorationStyle.wavy,
decorationColor: Colors.indigo,
decorationThickness: 3,
),
onSelected: (MatchResultItem match) => _onWordMatchTap(match),
onTapInto: (MatchResultItem match) => _onWordMatchTap(match),
),
],
);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
body: ListView(
padding: const EdgeInsets.all(16),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton.icon(
onPressed: () {
setState(() => enableHighlight = !enableHighlight);
controller.enableHighlight = enableHighlight;
},
icon: Icon(enableHighlight ? Icons.check : Icons.clear),
label: const Text('Highligting')),
ElevatedButton.icon(
onPressed: () {
setState(() => enableOnTapInto = !enableOnTapInto);
controller.enableOnTapInto = enableOnTapInto;
},
icon: Icon(enableOnTapInto ? Icons.check : Icons.clear),
label: const Text('On-Tap-Into')),
ElevatedButton.icon(
onPressed: () {
setState(() => enableOnSelected = !enableOnSelected);
controller.enableOnSelected = enableOnSelected;
},
icon: Icon(enableOnSelected ? Icons.check : Icons.clear),
label: const Text('On-Selected')),
],
),
const SizedBox(height: 16),
// ------------------------------------------------------------
// CONTEOLLER EXAMPLE
// ------------------------------------------------------------
const Text('TextField'),
TextField(controller: controller, maxLines: null),
const SizedBox(height: 16),
if (matchTappedItem != null)
Text(matchTappedItem.toString())
else
const Text('Select / Tap a matched word!',
style: TextStyle(
color: Colors.red, fontWeight: FontWeight.bold)),
const Divider(height: 64),
// ------------------------------------------------------------
// WRAPPER EXAMPLE
// ------------------------------------------------------------
const Text('RichWrapper'),
RichWrapper(
initialText: 'Good morning and good night at Github',
targets: [
MatchTargetItem.string('good',
style: const TextStyle(color: Colors.red)),
MatchTargetItem.strings(['morning', 'night'],
style: const TextStyle(color: Colors.blue)),
MatchTargetItem.regex(RegExp(r'and'),
style: const TextStyle(color: Colors.orange)),
MatchTargetItem.regexes([RegExp(r'at'), RegExp(r'Github')],
style: const TextStyle(color: Colors.indigo)),
],
child: (controller) => TextField(controller: controller),
),
],
),
),
),
);
}
}