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

描述

先上效果图

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

在项目中,有 @ 和 话题功能,需要在编辑时即可回显,但是官方原生的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)

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

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

 

 

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

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

 

 

 "基本文本输入域"

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

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

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

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

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

 

 

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

 1 import 'package:flutter/cupertino.dart';
 2 
 3 /// 范围样式,规定不同范围不同样式
 4 class RangeStyle extends Comparable<RangeStyle> {
 5   RangeStyle({@required this.range, this.style});
 6 
 7   /// 范围
 8   final TextRange range;
 9 
10   /// 指定样式
11   final TextStyle style;
12 
13   @override
14   int compareTo(RangeStyle other) {
15     return range.start.compareTo(other.range.start);
16   }
17 
18   @override
19   String toString() {
20     return 'RangeStyle(range:$range, style:$style)';
21   }
22 }

代码地址: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)

 

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

 

上一篇:Flutter TextField怎样去除下划线及有焦点时颜色


下一篇:【Java】【组件及事件处理】计算器界面