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