Flutter 31: 圖解 TextPainter 與 TextSpan 小嘗試

??????大家在學(xué)習(xí) Flutter 時一定會用過 Text委刘,而對于一些復(fù)雜文本的處理可能會選擇 RichText像街,再進(jìn)一步规辱,使用 RichText 就一定要用 TextSpan ,小菜本以為可以做為一個小知識點進(jìn)行簡單學(xué)習(xí)赛糟,但是隨著深入嘗試發(fā)現(xiàn) TextSpan 涉及東西很多,很值得研究晒他,因此單獨整理一篇小博文。

??????RichText 富文本核心即 TextSpan逸贾,而 TextSpan 結(jié)構(gòu)很像 Android 中的 ViewGroup 樹型結(jié)構(gòu)陨仅。

TextSpan 樹形結(jié)構(gòu).png

RichText 日常用法

??????小菜理解為 RichText 是進(jìn)階版的 Text津滞,如下直接看實例:

  1. TextDirection 用來控制文字位置,居左或居右邊灼伤;當(dāng)與 TextAlign 屬性共存時触徐,優(yōu)先看整體,以 TextAlign 為準(zhǔn)狐赡;
Widget richTextWid01() {
  return RichText(
      text: TextSpan(
          text: 'TextDirection.ltr 文字默認(rèn)居左',
          style: TextStyle(fontSize: 16.0, color: Colors.black)),
      textDirection: TextDirection.ltr);
}

Widget richTextWid02() {
  return RichText(
      text: TextSpan(
          text: 'TextDirection.rtl 文字默認(rèn)居右',
          style: TextStyle(fontSize: 16.0, color: Colors.black)),
      textDirection: TextDirection.rtl);
}

Widget richTextWid03() {
  return RichText(
      text: TextSpan(
          text: 'textDirection 與 textAlign 同時設(shè)置撞鹉,優(yōu)先看整體,文字居中',
          style: TextStyle(fontSize: 16.0, color: Colors.black)),
      textDirection: TextDirection.rtl,
      textAlign: TextAlign.center);
}
  1. RichText 可以借助 TextSpan 實現(xiàn)文字的多種效果颖侄,小菜認(rèn)為有點像文字效果拼接鸟雏,每個 TextSpan 可以設(shè)置單獨效果;
Widget richTextWid04() {
  return RichText(
      text: TextSpan(
          text: '多種樣式览祖,如:',
          style: TextStyle(fontSize: 16.0, color: Colors.black),
          children: <TextSpan>[
            TextSpan(
                text: '紅色',
                style: TextStyle(fontSize: 18.0, color: Colors.red)),
            TextSpan(
                text: '綠色',
                style: TextStyle(fontSize: 18.0, color: Colors.green)),
            TextSpan(
                text: '藍(lán)色',
                style: TextStyle(fontSize: 18.0, color: Colors.blue)),
            TextSpan(
                text: '白色',
                style: TextStyle(fontSize: 18.0, color: Colors.white)),
            TextSpan(
                text: '紫色',
                style: TextStyle(fontSize: 18.0, color: Colors.purple)),
            TextSpan(
                text: '黑色',
                style: TextStyle(fontSize: 18.0, color: Colors.black))
          ]),
      textAlign: TextAlign.center);
}
  1. TextSpan 可以借助 recognizer 設(shè)置點擊事件孝鹊,包括點擊/長按等;
final TapGestureRecognizer recognizer = TapGestureRecognizer();
void initState() {
  super.initState();
  recognizer.onTap = () {
    Toast.show('您好展蒂,歡迎點贊或關(guān)注!', context,
        duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
  };
}

Widget richTextWid05() {
  return RichText(
      text: TextSpan(
          text: 'recognizer 為手勢識別者又活,可設(shè)置點擊事件,',
          style: TextStyle(fontSize: 17.0, color: Colors.black),
          children: <TextSpan>[
        TextSpan(
            text: '點我試試',
            style: TextStyle(fontSize: 17.0, color: Colors.blue),
            recognizer: recognizer)
      ]));
}

TextPainter 日常用法

??????RichText 的使用很方便锰悼,但如果在深入了解 TextSpan 就有很多趣味了柳骄;Flutter 提供了和 Android 類似的 Canvas 繪制方法,但是 Canvas 卻不支持 drawText松捉,如果想要實現(xiàn)繪制文字夹界,就需要 TextPainter 而其內(nèi)部主要是由 TextSpan 實現(xiàn)。

??????使用 TextPainter 時需要繼承 CustomPainter隘世,并實現(xiàn) paintshouldRepaint 方法可柿,主要是在 paint 中進(jìn)行繪制 TextPainter。與 RichText 功能相同丙者,可以完全實現(xiàn) RichText 效果复斥;

??????TextPainter 繪制需要實現(xiàn) layoutpaint 方法,即繪制位置與繪制范圍械媒。

  1. TextDirectionTextAlign 效果與 RichText 一致目锭,但是 TextPainter 繪制時需要設(shè)置 layout 的最大最小范圍,而此時纷捞,文字位置與 layout 有關(guān)痢虹;當(dāng)文字長度小于設(shè)置的 minWidth 最小寬度時,以 minWidth 寬度為限制居左/居右/居中等主儡;而當(dāng)文字長度大于設(shè)置的 minWidth 最小寬度時奖唯,以 maxWidth 最大寬度為限制,包括換行等糜值;
TextPainter(
    text: TextSpan(
        text: 'TextDirection.ltr 文字默認(rèn)居左',
        style: TextStyle(fontSize: 16.0, color: Colors.black)),
    textDirection: TextDirection.ltr)
  ..layout(maxWidth: Screen.width, minWidth: Screen.width)
  ..paint(canvas, Offset(0.0, 0.0));
TextPainter(
    text: TextSpan(
        text: 'TextDirection.rtl 文字默認(rèn)居右',
        style: TextStyle(fontSize: 16.0, color: Colors.black)),
    textDirection: TextDirection.rtl)
  ..layout(maxWidth: Screen.width, minWidth: Screen.width)
  ..paint(canvas, Offset(0.0, 24.0));
TextPainter(
    text: TextSpan(
        text: 'textDirection 與 textAlign 同時設(shè)置丰捷,優(yōu)先看整體坯墨,文字居中',
        style: TextStyle(fontSize: 16.0, color: Colors.black)),
    textDirection: TextDirection.rtl,
    textAlign: TextAlign.center)
  ..layout(maxWidth: Screen.width, minWidth: Screen.width)
  ..paint(canvas, Offset(0.0, 48.0));
TextPainter(
    text: TextSpan(
        text: '文字位置與 layout 的最大最小寬度有關(guān)',
        style: TextStyle(fontSize: 16.0, color: Colors.black)),
    textDirection: TextDirection.rtl)
  ..layout(maxWidth: Screen.width - 100.0, minWidth: Screen.width - 200.0)
  ..paint(canvas, Offset(0.0, 90.0));
TextPainter(
    text: TextSpan(
        text: '文字長度較小',
        style: TextStyle(fontSize: 16.0, color: Colors.black)),
    textDirection: TextDirection.rtl)
  ..layout(maxWidth: Screen.width - 100.0, minWidth: Screen.width - 140.0)
  ..paint(canvas, Offset(0.0, 124.0));
  1. 而對于繪制多效果的樣式也是很方便,與 RichText 基本一致病往;
TextPainter(
    text: TextSpan(
        text: '多種樣式捣染,如:',
        style: TextStyle(fontSize: 16.0, color: Colors.black),
        children: <TextSpan>[
          TextSpan(
              text: '紅色',
              style: TextStyle(fontSize: 18.0, color: Colors.red)),
          TextSpan(
              text: '綠色',
              style: TextStyle(fontSize: 18.0, color: Colors.green)),
          TextSpan(
              text: '藍(lán)色',
              style: TextStyle(fontSize: 18.0, color: Colors.blue)),
          TextSpan(
              text: '白色',
              style: TextStyle(fontSize: 18.0, color: Colors.white)),
          TextSpan(
              text: '\n紫色',
              style: TextStyle(fontSize: 18.0, color: Colors.purple)),
          TextSpan(
              text: '黑色',
              style: TextStyle(fontSize: 18.0, color: Colors.black))
        ]),
    textDirection: TextDirection.ltr,
    textAlign: TextAlign.center)
  ..layout(maxWidth: Screen.width, minWidth: Screen.width)
  ..paint(canvas, Offset(0.0, 148.0));
  1. 小菜一直有問題的就是設(shè)置點擊事件,小菜以為與 RichText 一樣直接傳遞 recognizer 即可停巷,但始終無法調(diào)起耍攘,希望有解決過這個問題的朋友多多指導(dǎo),如下是小菜的測試代碼叠穆;
TextPainter(
    text: TextSpan(
        text: 'recognizer 為手勢識別者少漆,可設(shè)置點擊事件,',
        style: TextStyle(fontSize: 17.0, color: Colors.black),
        children: <TextSpan>[
          TextSpan(
              text: '測試暫時有誤硼被,待研究',
              style: TextStyle(fontSize: 17.0, color: Colors.blue))
        ],
        recognizer: TapGestureRecognizer()
          ..onTap = () {
            print('===測試暫時有誤示损,待研究==');
          }),
    textDirection: TextDirection.ltr,
    textAlign: TextAlign.center)
  ..layout(maxWidth: Screen.width - 40.0, minWidth: Screen.width - 40.0)
  ..paint(canvas, Offset(20.0, 200.0));
  1. 小菜認(rèn)為最有意思的就是 TextSpanstyleheight 屬性,在 TextSpan 中此值設(shè)置行高嚷硫,是以文字基準(zhǔn)線為最小距離检访;
TextPainter(
    text: TextSpan(
        text: 'TextPainter 小嘗試',
        style: TextStyle(fontSize: 20.0, color: Colors.black54),
        children: <TextSpan>[
          TextSpan(
              text: '\n作者:和尚(height:1.6)',
              style: TextStyle(
                  fontSize: 14.0, color: Colors.black54, height: 1.6))
        ]),
    textDirection: TextDirection.ltr,
    textAlign: TextAlign.center)
  ..layout(maxWidth: Screen.width, minWidth: Screen.width)
  ..paint(canvas, Offset(0.0, 20.0));
TextPainter(
    text: TextSpan(
        text: 'TextPainter 小嘗試',
        style: TextStyle(fontSize: 20.0, color: Colors.black54),
        children: <TextSpan>[
          TextSpan(
              text: '\n作者:和尚(height:3.0)',
              style: TextStyle(
                  fontSize: 14.0, color: Colors.black54, height: 3.0))
        ]),
    textDirection: TextDirection.ltr,
    textAlign: TextAlign.center)
  ..layout(maxWidth: Screen.width, minWidth: Screen.width)
  ..paint(canvas, Offset(0.0, 90.0));
TextPainter(
    text: TextSpan(
        text: 'TextPainter 小嘗試(height:0.1)',
        style:
            TextStyle(fontSize: 20.0, color: Colors.black54, height: 0.1),
        children: <TextSpan>[
          TextSpan(
              text: '\nTextPainter 小嘗試(height:0.1)',
              style: TextStyle(
                  fontSize: 20.0, color: Colors.black54, height: 0.1)),
          TextSpan(
              text: '\nTextPainter 小嘗試(height:0.1)',
              style: TextStyle(
                  fontSize: 20.0, color: Colors.black54, height: 0.1))
        ]),
    textDirection: TextDirection.ltr,
    textAlign: TextAlign.center)
  ..layout(maxWidth: Screen.width, minWidth: Screen.width)
  ..paint(canvas, Offset(0.0, 220.0));

??????如果有不對的地方還希望多多指出。

來源:阿策小和尚

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仔掸,一起剝皮案震驚了整個濱河市脆贵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌起暮,老刑警劉巖卖氨,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異负懦,居然都是意外死亡筒捺,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門纸厉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來系吭,“玉大人,你說我怎么就攤上這事颗品】铣撸” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵躯枢,是天一觀的道長则吟。 經(jīng)常有香客問我,道長锄蹂,這世上最難降的妖魔是什么逾滥? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上寨昙,老公的妹妹穿的比我還像新娘。我一直安慰自己掀亩,他們只是感情好舔哪,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著槽棍,像睡著了一般捉蚤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上炼七,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天缆巧,我揣著相機與錄音,去河邊找鬼豌拙。 笑死陕悬,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的按傅。 我是一名探鬼主播捉超,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼唯绍!你這毒婦竟也來了拼岳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤况芒,失蹤者是張志新(化名)和其女友劉穎惜纸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绝骚,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡耐版,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了皮壁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片椭更。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蛾魄,靈堂內(nèi)的尸體忽然破棺而出虑瀑,到底是詐尸還是另有隱情,我是刑警寧澤滴须,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布舌狗,位于F島的核電站,受9級特大地震影響扔水,放射性物質(zhì)發(fā)生泄漏痛侍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望主届。 院中可真熱鬧赵哲,春花似錦、人聲如沸君丁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绘闷。三九已至橡庞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間印蔗,已是汗流浹背扒最。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留华嘹,地道東北人吧趣。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像除呵,于是被迫代替她去往敵國和親再菊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容