Flutter: simply make a content highlight

Content highlighting is no stranger, especially on the search content page, it can be seen everywhere. Take Nuggets as an example, for a certain keyword, after we search, the content that is the same as the keyword will be highlighted ,As shown below:

The above effect can be said to be extremely simple to implement in Flutter. After all, the native components are provided for us, that is, the rich text component RichText.

For today's content, simply make an outline, the main content is as follows:

1. The simple effect of the case

2. Know RichText

3. Text highlighting implements logic

4. Highlight component source code

1. The simple effect of the case

1. Simple content highlighting

2. Content display in list form

Two, know RichText

To achieve the highlight effect, then we must understand the rich text component RichText, then again, what is rich text? To put it simply, it is a special text format, which is more colorful than ordinary text. It can contain various fonts, colors, sizes and other elements to make the text more vivid and interesting. For example, in our common scenarios such as reading agreements, you can Use rich text, which is an effect that native text cannot achieve.

First knowledge structure

It should be noted that the text here is different from the text in the text Text. The text Text refers to a string, and the text here refers to InlineSpan. Of course, InlineSpan is an abstract base class. Generally, we use TextSpan .

RichText({
    super.key,
    required this.text,
    this.textAlign = TextAlign.start,
    this.textDirection,
    this.softWrap = true,
    this.overflow = TextOverflow.clip,
    this.textScaleFactor = 1.0,
    this.maxLines,
    this.locale,
    this.strutStyle,
    this.textWidthBasis = TextWidthBasis.parent,
    this.textHeightBehavior,
    this.selectionRegistrar,
    this.selectionColor,
  }) : assert(text != null),
       assert(textAlign != null),
       assert(softWrap != null),
       assert(overflow != null),
       assert(textScaleFactor != null),
       assert(maxLines == null || maxLines > 0),
       assert(textWidthBasis != null),
       assert(selectionRegistrar == null || selectionColor != null),
       super(children: _extractChildren(text));

An overview of common construction properties:

const TextSpan({
    this.text,
    this.children,
    super.style,
    this.recognizer,
    MouseCursor? mouseCursor,
    this.onEnter,
    this.onExit,
    this.semanticsLabel,
    this.locale,
    this.spellOut,
  }) : mouseCursor = mouseCursor ??
         (recognizer == null ? MouseCursor.defer : SystemMouseCursors.click),
       assert(!(text == null && semanticsLabel != null));

Attributes

type

overview

textAlign

TextAlign

text alignment

TextAlign.left
TextAlign.right
TextAlign.cente
TextAlign.justify
TextAlign.start
TextAlign.end

textDirection

TextDirection

the direction of the text

TextDirection.ltr
TextDirection.rtl

overflow

TextOverflow

How to handle text overflow
TextOverflow.clip: Clip the overflowing text to fill the container.
TextOverflow.fade: Fade overflowing text to transparent.
TextOverflow.ellipsis: Use an ellipsis to indicate that the text has overflowed.
TextOverflow.visible: renders overflowing text outside the container

maxLines

int

Maximum number of lines

textWidthBase

TextWidthBase

text width

TextWidthBasis.parent

TextWidthBasis.longestLine

Common properties of TextSpan

Attributes

illustrate

text

Text of type String

children

Subassembly

style

The text style of the TextStyle type can set the size, color, style, etc. of the text

recognizer

Specify the gesture interaction
recognizer: TapGestureRecognizer()..onTap = () {}, which can listen to click events

Simple case:

RichText(
            text: const TextSpan(children: [
              TextSpan(text: "床前明月光,", style: TextStyle(color: Colors.black)),
              TextSpan(text: "疑是地上霜。", style: TextStyle(color: Colors.red)),
              TextSpan(text: "举头望明月,", style: TextStyle(color: Colors.blueAccent)),
              TextSpan(text: "低头思故乡。", style: TextStyle(color: Colors.tealAccent))
            ])

Effect:

Of course, in addition to the above-mentioned writing method, you can also use Text.rich to achieve, the code is as follows:

 const Text.rich(TextSpan(children: [
            TextSpan(text: "床前明月光,", style: TextStyle(color: Colors.black)),
            TextSpan(text: "疑是地上霜。", style: TextStyle(color: Colors.red)),
            TextSpan(text: "举头望明月,", style: TextStyle(color: Colors.blueAccent)),
            TextSpan(text: "低头思故乡。", style: TextStyle(color: Colors.tealAccent))
          ]))

3. The highlighting of the text realizes the logic

RichText can implement a rich text display, so how to use this component to highlight a certain content? First of all, we need to understand that the highlighted content is not fixed, and each character of a piece of content may be highlighted, so for TextSpan, we need to create it dynamically, and then dynamically change its style.

The dynamics here are also very simple, nothing more than the interception of strings, which are intercepted at the beginning, end, and middle, as shown in the figure below.

Of course, it should be noted that the content that may be searched exists in many places in the entire content. At this time, for the above logic, it is necessary to traverse the loop until the last searched content is found.

The main logic is as follows:

 //搜索内容为空
    if (_searchContent == "") {
      return Text(
        _content,
        style: _ordinaryStyle,
      );
    }
    List<TextSpan> richList = [];
    int start = 0;
    int end;

    //遍历,进行多处高亮
    while ((end = _content.indexOf(_searchContent, start)) != -1) {
      //如果搜索内容在开头位置,直接高亮,此处不执行
      if (end != 0) {
        richList.add(TextSpan(
            text: _content.substring(start, end), style: _ordinaryStyle));
      }
      //高亮内容
      richList.add(TextSpan(text: _searchContent, style: _highlightStyle));
      //赋值索引
      start = end + _searchContent.length;
    }
    //搜索内容只有在开头或者中间位置,才执行
    if (start != _content.length) {
      richList.add(TextSpan(
          text: _content.substring(start, _content.length),
          style: _ordinaryStyle));
    }

    return RichText(
      text: TextSpan(children: richList),
    );

4. Highlight component source code

The source code is very simple and can be used in combination with list components or alone. Of course, there are some special needs, such as increasing the text or changing the background, etc., can be expanded.

class TextHighlight extends StatelessWidget {
  final TextStyle _ordinaryStyle; //普通的样式
  final TextStyle _highlightStyle; //高亮的样式
  final String _content; //文本内容
  final String _searchContent; //搜索的内容

  const TextHighlight(this._content, this._searchContent, this._ordinaryStyle,
      this._highlightStyle,
      {super.key});

  @override
  Widget build(BuildContext context) {
    //搜索内容为空
    if (_searchContent == "") {
      return Text(
        _content,
        style: _ordinaryStyle,
      );
    }
    List<TextSpan> richList = [];
    int start = 0;
    int end;

    //遍历,进行多处高亮
    while ((end = _content.indexOf(_searchContent, start)) != -1) {
      //如果搜索内容在开头位置,直接高亮,此处不执行
      if (end != 0) {
        richList.add(TextSpan(
            text: _content.substring(start, end), style: _ordinaryStyle));
      }
      //高亮内容
      richList.add(TextSpan(text: _searchContent, style: _highlightStyle));
      //赋值索引
      start = end + _searchContent.length;
    }
    //搜索内容只有在开头或者中间位置,才执行
    if (start != _content.length) {
      richList.add(TextSpan(
          text: _content.substring(start, _content.length),
          style: _ordinaryStyle));
    }

    return RichText(
      text: TextSpan(children: richList),
    );
  }
}

The case Demo is very simple. The top is the search box, and the bottom is the displayed content, so I won’t post it here. The highlight component has been provided for you, and you can copy and use it directly.

Guess you like

Origin blog.csdn.net/ming_147/article/details/132281349