描述

先上效果图

Flutter 实现不同样式(有样式) 的TextField (可自定义),类似微博#话题#、@用户,(给TextField加TextSpan)-LMLPHP

在项目中,有 @ 和 话题功能,需要在编辑时即可回显,但是官方原生的TextField不支持对部分文字定义不同的样式,所以封装了一个。

注意:这不是富文本插件,不支持在输入框中显示图片,仅是 TextField 的扩展,让其支持自定义 TextSpan。

本文介绍封装思路,如果想要直接在项目中应用,可以直接通过以下方式引入:

插件地址:https://pub.dev/packages/text_span_field

text_span_field: 1.0.0

使用方式为:

TextSpanField(
controller: TextEditingController(
text: "这是一条测试信息,你们看他的颜色",
),
rangeStyles: [
RangeStyle(
range: TextRange(start: 0, end: 1),
style: TextStyle(color: Color(0xFF5BA2FF)),
),
RangeStyle(
range: TextRange(start: 3, end: 4),
style: TextStyle(color: Color(0xFF9C7BFF)),
),
],
),

正文

项目地址:https://github.com/JiangJuHong/FlutterTextSpanField

项目结构:

Flutter 实现不同样式(有样式) 的TextField (可自定义),类似微博#话题#、@用户,(给TextField加TextSpan)-LMLPHP

首先,我们要在TextField中进行扩展,必要的查看源代码,直接跳转到 build 渲染,发现代码如下:

Flutter 实现不同样式(有样式) 的TextField (可自定义),类似微博#话题#、@用户,(给TextField加TextSpan)-LMLPHP

TextField内部使用的是EditableText,在Flutter官网介绍如如下:

Flutter 实现不同样式(有样式) 的TextField (可自定义),类似微博#话题#、@用户,(给TextField加TextSpan)-LMLPHP

"基本文本输入域"

EditableText 组件内部有一个可重写方法 buildTextSpan,它定义了内容如何展示在输入框中,默认未经过处理,我们需要展示不同的内容,则需要重写该方法并根据要求进行封装。

第一步:继承 EditableText 并重写 buildTextSpan 属性

因此我们创建一个名叫 “EditableTextSpan”的组件,并继承了EditableText,然后重写了buildTextSpan,经过重写的代码如下:

Flutter 实现不同样式(有样式) 的TextField (可自定义),类似微博#话题#、@用户,(给TextField加TextSpan)-LMLPHP

代码地址:https://github.com/JiangJuHong/FlutterTextSpanField/blob/master/lib/editable_text_span.dart

其中 rangeStyle 为自定义范围样式类,方便组件使用时传递,rangeStyle代码为:

 import 'package:flutter/cupertino.dart';

 /// 范围样式,规定不同范围不同样式
class RangeStyle extends Comparable<RangeStyle> {
RangeStyle({@required this.range, this.style}); /// 范围
final TextRange range; /// 指定样式
final TextStyle style; @override
int compareTo(RangeStyle other) {
return range.start.compareTo(other.range.start);
} @override
String toString() {
return 'RangeStyle(range:$range, style:$style)';
}
}

代码地址:https://github.com/JiangJuHong/FlutterTextSpanField/blob/master/lib/range_style.dart

重写的 buildTextSpan 中主要的业务逻辑为根据 TextRange 定义的范围,应用不同的 TextStyle

第二步:重新封装TextField

buildTextSpan重写完毕后,默认的TextField并不会使用我们重写过后的文件,所以我们需要进行如下步骤操作:

1. 将 TextField的文件拷贝出来后命名为TextSpanField,随后将 build 方法中的EditableText 替换成EditableTextSpan。

Flutter 实现不同样式(有样式) 的TextField (可自定义),类似微博#话题#、@用户,(给TextField加TextSpan)-LMLPHP

2. 在 TextSpanField 中公开 rangeStyle 属性,并传递给 EditabledTextSpan

代码地址:https://github.com/JiangJuHong/FlutterTextSpanField/blob/master/lib/text_span_field.dart

结束

到这一步,我们组件已经封装完成,可以实现对不同的范围渲染不同的样式。

使用方法:

TextSpanField(
controller: TextEditingController(
text: "这是一条测试信息,你们看他的颜色",
),
rangeStyles: [
RangeStyle(
range: TextRange(start: 0, end: 1),
style: TextStyle(color: Color(0xFF5BA2FF)),
),
RangeStyle(
range: TextRange(start: 3, end: 4),
style: TextStyle(color: Color(0xFF9C7BFF)),
),
],
),

  

由于本文章并未精准讲解每一行代码,可能需要结合源代码一起研究,源代码地址为:https://github.com/JiangJuHong/FlutterTextSpanField/tree/master/lib

该内容已封装为插件 text_span_field ,由于并未对原生内容进行改动,所以兼容TextField,理论上在TextField支持的操作,在TextSpanField同样支持。

我的主页:https://github.com/JiangJuHong

05-22 00:53