Home > Enterprise >  Flutter - Find replace and style certain string pattern in a list
Flutter - Find replace and style certain string pattern in a list

Time:09-09

I have a list of strings that loaded from json file as below:

It was getting [color="black"]dark[/color], and we weren’t [color="blue"]there[/color] yet.
They got [color="black"]there[/color] early, and they got really [color="black"]good[/color] seats.
Mr. Montoya knows the way to the [color="black"]bakery[/color] even though he's never been [color="blue"]there[/color].

How to use listview.builder to find each text that is wrap within [color="..."][/color] and add text style color or Widget to it?
For example [color="blue"]there[/color] become there (with color blue)

CodePudding user response:

Here's a working example. Not sure if it's the best way, because it's a bit hacky but gets the job done:

import 'package:flutter/material.dart';

void main() {
  List<String> sentences = [
    'It was getting [color="black"]dark[/color], and we weren’t [color="blue"]there[/color] yet.',
    'They got [color="black"]there[/color] early, and they got really [color="black"]good[/color] seats.',
    '''Mr. Montoya knows the way to the [color="black"]bakery[/color] even though he's never been [color="blue"]there[/color].'''
  ];

  runApp(MaterialApp(
      home: Scaffold(
    body: ListView.builder(
        itemCount: sentences.length,
        itemBuilder: (context, index) =>
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: TextWithColors(text: sentences[index]),
            )),
  )));
}

class TextWithColors extends StatelessWidget {
  final String text;
  static final regex = RegExp("(?=\\[)|(?<=\\])");

  const TextWithColors({Key? key, required this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final split = text.split(regex);
    Color currentColor = Colors.grey;
    return RichText(
        text: TextSpan(
      children: <InlineSpan>[
        for (String text in split)
          text.startsWith('[')
              ? TextSpan(
                  style: TextStyle(
                      color: currentColor = text.contains('"black"')
                          ? Colors.black
                          : text.contains('"blue"')
                              ? Colors.blue
                              : Colors.grey))
              : TextSpan(text: text, style: TextStyle(color: currentColor)),
      ],
    ));
  }
}

Output:

enter image description here

CodePudding user response:

You need to use regular expression that will change your strings into multiple TextSpan's that you can combine. so your [color=black]black[/color] will become

TextSpan(text: 'black', style: const TextStyle(color: Colors.black))

I took it from other stackoverflow question

You should use the RichText widget.

A RichText widget will take in a TextSpan widget that can also have a list of children TextSpans.

Each TextSpan widget can have a different TextStyle.

Here is the example code to render: Hello World

var text = RichText(
  text: TextSpan(
    // Note: Styles for TextSpans must be explicitly defined.
    // Child text spans will inherit styles from parent
    style: const TextStyle(
      fontSize: 14.0,
      color: Colors.black,
    ),
    children: <TextSpan>[
      TextSpan(text: 'Hello'),
      TextSpan(text: 'World', style: const TextStyle(fontWeight: FontWeight.bold)),
    ],
  ),
);
  • Related