flutterdartrichtextlanguagetool

flutter - richtext, textspan from a list


I don't have much experience with flutter.

I would like to use the language_tool library (https://pub.dev/packages/language_tool) for Dart and Flutter.

I'm trying to create a text where the errors found by the tool() function are clickable.

To do this I thought of using the RichText widget with TextSpan as described here: Make specific parts of a text clickable in flutter

For now I have written this code, but I don't know how to go on

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

void main() => runApp(mainApp());

class mainApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Chat(),
    );
  }
}

class Chat extends StatefulWidget {
  const Chat({Key? key}) : super(key: key);

  @override
  _ChatState createState() => _ChatState();
}

class _ChatState extends State<Chat> {
  String text = 'Henlo i am Gabriele';

  List<WritingMistake> mistakes = [];

  List<TextSpan> richtext = [];

  void tool(String text) async {
    var tool = LanguageTool();
    var result = tool.check(text);
    var correction = await result;

    for (var m in correction) {
      WritingMistake mistake = WritingMistake(
        message: m.message,
        offset: m.offset,
        length: m.length,
        issueType: m.issueType,
        issueDescription: m.issueDescription,
        replacements: m.replacements,
      );

      mistakes.add(mistake);
    }

    print(mistakes.length);
    print(mistakes);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: ListView(
          children: [
            Container(
              color: Colors.red,
              height: 150.0,
              width: double.infinity,
              child: Center(
                  child: Text(text, style: const TextStyle(fontSize: 20.0))),
            ),
            Container(
              color: Colors.blue,
              height: 150.0,
              width: double.infinity,
              child: Center(
                child: Container(
                  child: RichText(
                    text: TextSpan(
                      text: '',
                      style: TextStyle(color: Colors.black),
                      children: richtext,
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

I hope I was clear and that someone can help me.

Thank you :)


Solution

  • Here is a small example of what your clickable words should look like in the content. Copy and paste into DartPad to play with it.

    import 'package:flutter/material.dart';
    import 'package:flutter/gestures.dart';
    
    void main() => runApp(App());
    
    class App extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: Chat(),
        );
      }
    }
    
    class Chat extends StatefulWidget {
      const Chat({Key? key}) : super(key: key);
    
      @override
      _ChatState createState() => _ChatState();
    }
    
    class _ChatState extends State<Chat> {
      List<String> mistakes = ['bugs', 'error'];
      String content = 'Your application status is error free'
          ' and no bugs were found.';
    
      Future<void> onTap(String text) async {
        print(text);
      }
    
      @override
      Widget build(BuildContext context) {
        String text = 'Henlo i am Gabriele';
    
        return Scaffold(
          body: SafeArea(
            child: ListView(
              children: [
                Container(
                  color: Colors.red,
                  height: 150.0,
                  width: double.infinity,
                  child: Center(
                    child: Text(text, style: const TextStyle(fontSize: 20.0)),
                  ),
                ),
                Container(
                  color: Colors.blue,
                  height: 150.0,
                  width: double.infinity,
                  child: Center(
                    child: RichText(
                      text: TextSpan(
                        text: 'App status: ',
                        style: const TextStyle(color: Colors.black),
                        children: [
                          for (String word in content.split(' '))
                            if (mistakes.contains(word)) ...[
                              TextSpan(
                                text: word + ' ',
                                style: const TextStyle(fontWeight: FontWeight.bold),
                                recognizer: TapGestureRecognizer()
                                  ..onTap = () {
                                    // Do anything with the state on click.
                                    onTap(word);
                                  },
                              )
                            ] else ...[
                              TextSpan(text: word + ' ')
                            ],
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }