Home > Software design >  How to replace certain string/text in a list to Widget (GestureDetector) in Flutter
How to replace certain string/text in a list to Widget (GestureDetector) in Flutter

Time:09-07

I load a list of strings from json file. For example:
Joe waited for the <link>train</link>
The <link>car</link> was late
Mary and Samantha took the <link>bus</link>

In the listview.builder how to replace the text that is within <link></link> to be able to wrap in a GestureDetector widget?
From <link>train</link> to train (this train is clickable)
My code is as below:

ListView.builder(
   itemCount: book.sentence.length,
   itemBuilder: (context, index) {
      return Container(
         child: Row(
            children: [
               Flexible(
                  child: Text(book.sentence[index].content.toString())
                  )
               ],
          )
       );
    }
  ),

The current output result are:
Joe waited for the <link>train</link>
The <link>car</link> was late
Mary and Samantha took the <link>bus</link>

CodePudding user response:

Let say we have list Like this:

List<String> _testList = [
    'Joe waited for the <link>train</link>',
    'The <link>car</link> was late'
  ];

than try this:

ListView.builder(
              itemCount: _testList.length,
              itemBuilder: (context, index) {
                var text = _testList[index];

                if (text.contains('<link>')) {
                  var textList = text.split(' ');

                  final startIndex = text.indexOf('<link>');
                  final endIndex =
                      text.indexOf('</link>', startIndex   '<link>'.length);
                  var selectableText =
                      text.substring(startIndex   '<link>'.length, endIndex);
                  
                  var index = textList.indexOf('<link>$selectableText</link>');
                  var beforeString = '';
                  var afterString = '';
                  for (var i = 0; i < index; i  ) {
                    beforeString = beforeString   textList[i]   ' ';
                  }
                  if (index   1 != textList.length) {
                    for (var i = index   1; i < textList.length; i  ) {
                      afterString = afterString   textList[i]   ' ';
                    }
                  }

                  return Text.rich(
                    TextSpan(
                      children: [
                        TextSpan(text: beforeString),
                        WidgetSpan(
                          child: GestureDetector(
                            onTap: () {
                              print('$selectableText clicked');
                            },
                            child: Text(
                              selectableText,
                              style: TextStyle(fontWeight: FontWeight.bold),
                            ),
                          ),
                        ),
                        TextSpan(text: afterString),
                      ],
                    ),
                  );
                } else {
                  return Text(text);
                }
              },
            )

enter image description here

CodePudding user response:

Use RichText for each builder as follows, There you can add required style to indicate the text is clickable.

RichText(
      text: TextSpan(
        text: 'Joe waited for the ',
        style: DefaultTextStyle.of(context).style,
        children: <TextSpan>[
          TextSpan(
              text: 'train',
              style: const TextStyle(color: Colors.lightBlue),
              recognizer: TapGestureRecognizer()
                ..onTap = () => print('click')),
        ],
      ),
    ),
  • Related