Flutter 中 RichText、SelectableText 的使用詳解 | Flutter Widgets

這是我參與更文挑戰的第25天,活動詳情查看: 更文挑戰html

前言

前面咱們聊了 Flutter 中 Text 各類屬性樣式調配的展現效果,這篇咱們稍微深刻一點,看看 Text 的源碼以及富文本的使用,最後聊聊選擇文本的應用。git

image.png

RichText

Text 源碼

查看富文本以前,咱們先看看上篇的 Text 源碼,其實在上上篇咱們演示行高參數的時候就能夠看到雖然咱們使用的是 Text ,可是渲染時在 Widget 樹中看到的是 RichText
image.pnggithub

Text 源碼一覽

出現上述的緣由是什麼呢?咱們來瞅瞅源碼吧
image.png
首先 Text 繼承自 StatelessWidget ,下面咱們就直接看 build 方法便可。api

這裏看到上面註釋圈起來的部分,說 RichText 能夠更好的讓咱們控制文字樣式markdown

  • Text - build 方法

image.png
上面👆🏻能夠看出 build 方法最終返回的是 result (550 行),而 result 建立的就是 RichText 對象,通常咱們沒有給文字添加語義標籤 semanticsLabel ,因此就會直接返回 RichText Widget 了。less

如今咱們就知道爲啥咱們寫的是 Text ,但實際是 RichText 的 Widget 的緣由了ide

簡單富文本

上面咱們知道了緣由,下面咱們就從一個簡單的富文原本走進 RichText
image.png
👆🏻上面的效果,若是單獨使用 Text 寫是否是咱們要外部嵌套一個 Row+3個Text , 咱們還要考慮換行問題,這樣就比較麻煩了,若是咱們使用 RichText,就不須要考慮這麼多,關心樣式便可。oop

RichText(
  text: TextSpan(
    text: 'Flutter Widgets 已有 ',
    children: [
      TextSpan(
        text: '25',
        // 設置個性化覆蓋樣式
        style: TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 18,
        ),
      ),
      // 複用上層通用樣式
      TextSpan(text: ' 系列文章'),
    ],
    // 設置通用樣式
    style: TextStyle(
      color: Colors.blue,
    ),
  ),
)
複製代碼

這裏咱們主要關心樣式的設置,有 2 個點須要注意:post

  • 思想上要理解好這種 TextSpan 的嵌套關係
  • 要理解 style 的繼承和覆蓋關係

TextSpan

上面咱們使用到了 TextSpan ,來一塊兒看看他的屬性吧。ui

上源碼

image.png
這裏咱們看到 TextSpan 繼承自 InlineSpan ,實現了 HitTestTarget(命中檢測)和 MouseTrackerAnnotation (鼠標追蹤),屬性上也很是的簡單,經常使用的可能就是前 4 個,而後前 3 個咱們都瞭解使用過了,下面來看看第四個吧。

局部手勢檢測

我如今把 25 這個數字變成紅色,而且要加上點擊事件怎麼辦呢?這時候就用到了第 4 個屬性 recognizer

// 點擊手勢檢測器
late TapGestureRecognizer tapRecognizer;
@override
void initState() {
  tapRecognizer = TapGestureRecognizer()..onTap = _handleTap;
  super.initState();
}

/// 處理點擊
void _handleTap() {
  // 打印
  print('tapRecognizer 25');
  // 設置震動效果
  HapticFeedback.vibrate();
}
// 這裏只貼圖 25 的部分代碼
TextSpan(
  text: '25',
  // 設置個性化覆蓋樣式
  style: TextStyle(
    fontWeight: FontWeight.bold,
    fontSize: 18,
    color: Colors.red,
  ),
  // 設置點擊檢測器
  recognizer: tapRecognizer,
)
複製代碼
  • 顯示效果

image.png

  • 點擊後打印以下

image.png
這樣咱們再作,好比用戶協議與隱私政策的時候就能夠用到啦,能夠作單獨的樣式和跳轉。

WidgetSpan

上面咱們還只是說了富文本中文字多樣式的狀況,還有嵌套各類圖片的狀況,在實際富文本應用時比這個要複雜的多,文章中示例作核心的解法,具體還須要實際應用和創新。
image.png
若是在上面的基礎上咱們須要加上圖標怎麼處理呢?看看下面的代碼

RichText(
  text: TextSpan(
    children: [
      // Flutter Logo
      WidgetSpan(child: FlutterLogo()),
      TextSpan(text: 'Flutter Widgets 已有 '),
      TextSpan(
        text: '25',
        // 設置個性化覆蓋樣式
        style: TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 18,
          color: Colors.red,
        ),
        recognizer: tapRecognizer,
      ),
      // 連接圖標
      WidgetSpan(
        child: Icon(
          Icons.link,
          size: 16,
          color: Colors.blue,
        ),
      ),
      // 複用上層通用樣式
      TextSpan(text: ' 系列文章'),
      // 複製圖標
      WidgetSpan(
        child: Icon(
          Icons.copy,
          size: 16,
          color: Colors.grey,
        ),
      ),
    ],
    // 設置通用樣式
    style: TextStyle(
      color: Colors.blue,
    ),
  ),
)
複製代碼

這裏只是演示,實際項目中會根據下發的文本協議來解析,而後生成對應的 Widget 組合

Text.rich

另一種建立富文本的方式就是使用 Text.rich ,下面來一塊兒看看代碼吧

Text.rich(
  TextSpan(
    children: [
      WidgetSpan(child: FlutterLogo()),
      TextSpan(text: 'Flutter Widgets 已有 '),
      TextSpan(
        text: '25',
        // 設置個性化覆蓋樣式
        style: TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 18,
          color: Colors.red,
        ),
        recognizer: tapRecognizer,
      ),
      WidgetSpan(
        child: Icon(
          Icons.link,
          size: 16,
          color: Colors.blue,
        ),
      ),
      // 複用上層通用樣式
      TextSpan(text: ' 系列文章'),
      WidgetSpan(
        child: Icon(
          Icons.copy,
          size: 16,
          color: Colors.grey,
        ),
      ),
    ],
    // 設置通用樣式
    style: TextStyle(
      color: Colors.blue,
    ),
  ),
)
複製代碼

image.png

小總結

到這裏 RichText 基本就聊完了,基礎的樣式咱們在前 2 篇文章已經聊過,能夠在專欄中回看。

SelectableText

上面展現的文本都是沒法選擇複製的,在實際項目中,有些內容文字是須要支持用戶能夠選擇複製的,這時咱們就須要將 Text 改變成 SelectableText
image.png

代碼展現

SelectableText(
  "Text - ZeroFlutter",
  style: TextStyle(
    // 顏色藍色
    color: Colors.blue,
    // 字號 24
    fontSize: 24,
  ),
)
複製代碼

使用限制

在實際使用時,你會發現沒法指定溢出樣式了,默認就是直接剪裁掉了。
image.png
由於考慮到,複製確定是對全部文本進行操做,若是咱們溢出樣式是... 那麼複製出來就是展現的樣式,確定不符合需求。
因此在實際項目中,若是是長按複製所有可使用 Text ,選擇複製能夠 SelectableText

SelectableText.rich

Text.rich 一致,要使用富文本時,能夠直接使用 SelectableText.rich

可是這裏有個顯示就是咱們不能使用 WidgetSpan 了,只能使用 TextSpan

SelectableText.rich(
  TextSpan(
    children: [
      // WidgetSpan(child: FlutterLogo()),
      TextSpan(text: 'Flutter Widgets 已有 '),
      TextSpan(
        text: '25',
        // 設置個性化覆蓋樣式
        style: TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 18,
          color: Colors.red,
        ),
        recognizer: tapRecognizer,
      ),
      // WidgetSpan(
      // child: Icon(
      // Icons.link,
      // size: 16,
      // color: Colors.blue,
      // ),
      // ),
      // 複用上層通用樣式
      TextSpan(text: ' 系列文章'),
      // WidgetSpan(
      // child: Icon(
      // Icons.copy,
      // size: 16,
      // color: Colors.grey,
      // ),
      // ),
    ],
    // 設置通用樣式
    style: TextStyle(
      color: Colors.blue,
    ),
  ),
)
複製代碼

image.png

源碼倉庫

基於 Flutter 🔥 最新版本

參考連接

關注專欄

  • 此文章已收錄到下面👇 的專欄,能夠直接關注
  • 更多文章繼續閱讀|系列文章持續更新

👏 歡迎點贊➕收藏➕關注,有任何問題隨時在下面👇評論,我會第一時間回覆哦

相關文章
相關標籤/搜索