内容高亮并不陌生,特别是在搜索内容页面,可以说四处可见,就拿掘金这个应用而言,针对某一个关键字,我们搜索之后,与关键字相同的内容,则会高亮展示,如下图所示:
如上的效果,在Flutter当中,实现起来可以说是无比的简单,毕竟原生的组件都给我们提供了,那就是富文本组件RichText。
针对今天的内容,简单的列一个大纲,主要内容如下:
1、案例简单效果
2、认识RichText
3、文本的高亮实现逻辑
4、高亮组件源码
一、案例简单效果
1、简单的内容高亮展示
2、列表形式内容展示
二、认识RichText
要实现高亮效果,那么我们必须了解富文本组件RichText,话又说回来,什么是富文本呢?简单来说,它是一种特殊的文本格式,比普通文本更加丰富多彩,可以包含各种字体、颜色、大小等元素,使文本更加生动、有趣,比如我们常见的阅读协议等场景,均可采用富文本形式,这是原生的文本无法实现的效果。
初识构造
构造属性需要注意的是,这里的text,和文本Text中的text是不一样的,文本Text指的是字符串,这里的text指的是InlineSpan,当然了InlineSpan是抽象基类,一般我们使用TextSpan。
RichText({ super.key, requiredthis.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));
常见构造属性概述:
constTextSpan({ 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));
属性 |
类型 |
概述 |
textAlign |
TextAlign |
文本对齐方式 TextAlign.left |
textDirection |
TextDirection |
文本的方向 TextDirection.ltr |
overflow |
TextOverflow |
文字溢出的处理方式 |
maxLines |
int |
最大行数 |
textWidthBasis |
TextWidthBasis |
文本的宽度 TextWidthBasis.parent TextWidthBasis.longestLine |
TextSpan常见属性
属性 |
说明 |
text |
String类型的文本 |
children |
子组件 |
style |
TextStyle类型的文本样式可以设置文字的大小、颜色、样式等 |
recognizer |
指定手势交互 |
简单案例:
RichText( text: constTextSpan(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)) ])
效果:
当然了,除了上述写法之外,也可以使用Text.rich来实现,代码如下:
constText.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)) ]))
三、文本的高亮实现逻辑
RichText可以实现一个富文本展示,那么如何利用这个组件实现某个内容高亮展示呢?首先,我们要明白,高亮的内容是不固定的,一段内容的每个字符都有可能会高亮,所以针对TextSpan,我们就需要动态的创建,然后动态的改变其样式。
这里的动态也是十分的简单,无非就是字符串的截取,分别是开头、结尾、和中间三种情况进行截取,如下图所示。
当然了,需要注意,有可能要搜索的这个内容,在整个内容中是多处存在的,这个时候,针对以上的逻辑,就需要遍历循环了,直至找到最后一个搜索的内容。
主要的逻辑如下:
//搜索内容为空if (_searchContent=="") { returnText( _content, style: _ordinaryStyle, ); } List<TextSpan>richList= []; intstart=0; intend; //遍历,进行多处高亮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)); } returnRichText( text: TextSpan(children: richList), );
四、高亮组件源码
源码很简单,可以结合列表组件或者单独使用,当然了,有一些特殊需求,文字加大或者改变背景等需求,都可以进行扩展。
classTextHighlightextendsStatelessWidget { finalTextStyle_ordinaryStyle; //普通的样式finalTextStyle_highlightStyle; //高亮的样式finalString_content; //文本内容finalString_searchContent; //搜索的内容constTextHighlight(this._content, this._searchContent, this._ordinaryStyle, this._highlightStyle, {super.key}); Widgetbuild(BuildContextcontext) { //搜索内容为空if (_searchContent=="") { returnText( _content, style: _ordinaryStyle, ); } List<TextSpan>richList= []; intstart=0; intend; //遍历,进行多处高亮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)); } returnRichText( text: TextSpan(children: richList), ); } }
案例Demo很是简单,上边是搜索框,下面是展示的内容,这里就不贴了,高亮组件已经给大家提供了,大家可以直接复制使用。