111

Is there a way to detect which word in the TextSpan was touched by the user?

This paragraph is here to get round the stack overflow robot that is insisting that I write more stuff :)

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
adko
  • 1,113
  • 2
  • 7
  • 7

5 Answers5

203

You can improve by yourself

import 'package:flutter/gestures.dart';
...

RichText(
      text: TextSpan(text: 'Non touchable. ', children: [
        TextSpan(
          text: 'Tap here.',
          recognizer: TapGestureRecognizer()..onTap = () => print('Tap Here onTap'),
        )
      ]),
    );
Putra Ardiansyah
  • 5,249
  • 4
  • 25
  • 37
97

Screenshot:

enter image description here


Use recognizer property of TextSpan which allows almost all types of event.

RichText(
  text: TextSpan(
    children: [
      TextSpan(
        text: 'Single tap',
        style: TextStyle(color: Colors.red[300]),
        recognizer: TapGestureRecognizer()..onTap = () {
          // Single tapped.
        },
      ),
      TextSpan(
        text: ' Double tap',
        style: TextStyle(color: Colors.green[300]),
        recognizer:  DoubleTapGestureRecognizer()..onDoubleTap = () {
          // Double tapped.
        }
      ),
      TextSpan(
        text: ' Long press',
        style: TextStyle(color: Colors.blue[300]),
        recognizer: LongPressGestureRecognizer()..onLongPress = () {
          // Long Pressed.
        },
      ),
    ],
  ),
)

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
  • How do you pass the underlined text to the method which processes taps? – Alex Semeniuk Aug 06 '19 at 16:47
  • 1
    I suggest that you put the text in a variable and then you can use it in the tap handling closure @AlexSemeniuk – jlyonsmith Nov 10 '22 at 16:06
  • @jlyonsmith Yeah, I ended up doing exactly that: creating a map which links recognizers to their values, and filling it along the way. Can't think of any better solution. – Alex Semeniuk Nov 11 '22 at 17:49
9

Iterate over the string to get an array of strings, create separate text span for each and add the gesture recognizer

 List<TextSpan> createTextSpans(){
    final string = """Text seems like it should be so simple, but it really isn't.""";
    final arrayStrings = string.split(" ");
    List<TextSpan> arrayOfTextSpan = [];
    for (int index = 0; index < arrayStrings.length; index++){
      final text = arrayStrings[index] + " ";
      final span = TextSpan(
        text: text,
        recognizer: TapGestureRecognizer()..onTap = () => print("The word touched is $text")
      );
      arrayOfTextSpan.add(span);
    }
    return arrayOfTextSpan;
abubz
  • 91
  • 1
  • 2
1
late TapGestureRecognizer tapGestureRecognizer;

@override
    void initState() {
      super.initState();
    
      tapGestureRecognizer = TapGestureRecognizer()
        ..onTap = () {
          widget.onProfileDetails();
        };
    }
    
    @override
    void dispose() {
      super.dispose();
      tapGestureRecognizer.dispose();
    }
    
    @override
    Widget build(BuildContext context) {
      return Flexible(
        child: RichText(
          text: TextSpan(
            children: [
              TextSpan(
                text: widget.notificationObject.name,
                style: TextStyle(
                  fontSize: width * 0.044,
                  fontFamily: 'HelveticaNeueRegular',
                  color: Theme.of(context).primaryColor,
                ),
                recognizer: tapGestureRecognizer,
              ),
            ],
          ),
        ),
      );
    }
Muhammad Asif
  • 81
  • 1
  • 4
1
 RichText(
                text: TextSpan(
                  text: "If you don't have a account ",
                  style: TextStyle(
                    fontFamily: AppFonts.phagsPa,
                    fontSize: 16,
                    color: AppColors.white,
                  ),
                  children: [
                    TextSpan(
                      text: "sign-up".toUpperCase(),
                      style: TextStyle(
                        color: AppColors.btnBgColor,
                        fontWeight: FontWeight.bold,
                      ),
                      recognizer: TapGestureRecognizer()
                        ..onTap = () {
                          Get.to(() => MerchantSignupPage());
                        },
                    ),
                    TextSpan(text: " here")
                  ],
                ),
                textAlign: TextAlign.center,
              ),
  • Above solutions give error: Missing selector such as '.identifier' or '[0]'. Try adding a selector. –  Jun 30 '23 at 05:41