rich_text_controllerx 1.1.0 copy "rich_text_controllerx: ^1.1.0" to clipboard
rich_text_controllerx: ^1.1.0 copied to clipboard

An extended text editing controller that supports different inline styles for custom regex patterns

example/README.md

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),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
2
likes
160
points
6
downloads

Publisher

verified publishernovelplotter.com

Weekly Downloads

An extended text editing controller that supports different inline styles for custom regex patterns

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on rich_text_controllerx