描述
先上效果圖
在項目中,有 @ 和 話題功能,需要在編輯時即可回顯,但是官方原生的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
項目結構:
首先,我們要在TextField中進行擴展,必要的查看源代碼,直接跳轉到 build 渲染,發現代碼如下:
TextField內部使用的是EditableText,在Flutter官網介紹如如下:
"基本文本輸入域"
EditableText 組件內部有一個可重寫方法 buildTextSpan,它定義了內容如何展示在輸入框中,默認未經過處理,我們需要展示不同的內容,則需要重寫該方法並根據要求進行封裝。
第一步:繼承 EditableText 並重寫 buildTextSpan 屬性
因此我們創建一個名叫 “EditableTextSpan”的組件,並繼承了EditableText,然后重寫了buildTextSpan,經過重寫的代碼如下:
代碼地址: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。
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