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
專案結構:
首先,我們要在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
&n