Flutter 實現不同樣式(有樣式) 的TextField (可自定義),類似微博#話題#、@用戶,(給TextField加TextSpan)
- 2020 年 3 月 27 日
- 筆記
描述
先上效果圖
在項目中,有 @ 和 話題功能,需要在編輯時即可回顯,但是官方原生的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