欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Flutter中那些你需要知道的文本知識(shí)!-創(chuàng)新互聯(lián)

通過閱讀本文,您將了解到

創(chuàng)新互聯(lián)為客戶提供專業(yè)的成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、程序、域名、空間一條龍服務(wù),提供基于WEB的系統(tǒng)開發(fā). 服務(wù)項(xiàng)目涵蓋了網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站程序開發(fā)、WEB系統(tǒng)開發(fā)、微信二次開發(fā)、成都手機(jī)網(wǎng)站制作等網(wǎng)站方面業(yè)務(wù)。
  1. 文本的組成部分;
  2. Flutter對(duì)于文本&段落是如何繪制的;
  3. 明白Flutter Text 背后的邏輯;
  4. 在業(yè)務(wù)中碰到一些文本顯示的問題時(shí),知道從哪些地方去嘗試修改。
前言

文字是記錄語(yǔ)言的書寫符號(hào)系統(tǒng),是形、音、義的統(tǒng)一體,是人類最重要的輔助性 交際工具。作為一個(gè)Flutter開發(fā)者,我們都知道可以通過Text()這個(gè)文本組件將文字顯示出來。但是這其中的Flutter的字體是怎么組成的?Flutter文本是怎么構(gòu)建的?Render Tree是怎樣繪制文本的…作為本專欄(整個(gè)專欄都在與文本打交道)的第一篇文章,讓我們從這些原理細(xì)節(jié)講起。希望能對(duì)你認(rèn)識(shí)Flutter的文本渲染有所幫助。

注:本文的目的在于讓大家了解Flutter中的基本文本知識(shí),快速的帶大家了解渲染流程,但并未很深入的分析Flutter文本渲染的原理。

字體基礎(chǔ)理論通用部分

在整個(gè)網(wǎng)絡(luò)世界中,大家可以將字體理解為一個(gè)數(shù)字文件,它是一個(gè)包含特定大小、粗細(xì)和樣式的文件。它定義了每個(gè)字的形狀、大小和圖形。

例如Bariol_Regular.otf。.otf是字體文件格式。

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-SLGvJ6LK-1669544494694)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6b43356354404639bd7b54526a2970da~tplv-k3u1fbpfcp-watermark.image?)]

有了字體格式后,我們會(huì)碰到相同的字體大小卻有不同的顯示布局這個(gè)問題。因?yàn)槊恳粋€(gè)字體格式都定義了它自己的參考大小,每一個(gè)字符都是基于這個(gè)大小設(shè)計(jì)的。所以即使設(shè)置同樣的字體大小,也會(huì)有不同的布局。

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-M19SgzcN-1669544494696)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/541c8653d5964a3b9358d941b2ff3661~tplv-k3u1fbpfcp-watermark.image?)]

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-flIXYZLi-1669544494697)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/06896234fa3846469fb647a380bc607b~tplv-k3u1fbpfcp-watermark.image?)]

在Flutter中文本由哪些部分組成? Baseline
  • 在Flutter中,每一個(gè)字符都會(huì)在Baseline(基線)上。有了這個(gè)基線后,就算是不同大小的文字也可以處于同一水平線上。Baseline是非常重要的,因?yàn)榭梢酝ㄟ^它測(cè)量文本和元素之間的垂直距離。其他還有Middleline、BottomlineTopline。

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-VZO6UXAO-1669544494698)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2853b80fe819407b928a6fd93e29a859~tplv-k3u1fbpfcp-watermark.image?)]

  • Baseline的算法公式推導(dǎo)有興趣的朋友可以自行搜索。
Text Spacing
  • 文字間距是指一段文本中每個(gè)文字之間插入的空間。
  • 在Flutter中可以通過TextStyle下的wordSpacing設(shè)置單詞與單詞之間的間距,通過letterSpacing設(shè)置字符與字符之間的間距。

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-uyChiBG1-1669544494698)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/28a543c5d32840ee9f4a48d2ea333688~tplv-k3u1fbpfcp-watermark.image?)]

Weight
  • Weight是指字體筆畫的粗細(xì),在Flutter中通過fontWeight設(shè)置。

    常見的有:normalbold,其他還有FontWeight.w100…等粗細(xì)值

TextStyle(
  fontWeight: FontWeight.bold 
),
TextSpan

在Flutter中,我們經(jīng)常會(huì)使用Text()這個(gè)組件,但是我們通過閱讀Text()的源碼后就可以知道,它的build方法返回的就是RichText組件。所以它會(huì)呈現(xiàn)為TextSpan。Span指的是字符之間的行距。

@override
Widget build(BuildContext context) {
...
  Widget result = RichText(
    ...
    text: TextSpan(
      style: effectiveTextStyle,
      text: data,
      children: textSpan != null ?[textSpan!] : null,
    ),
  );
  ...
  return result;
}
Height

在Flutter中,定義了一個(gè)TextStyle.height,用于給呈現(xiàn)文本的TextSpan一個(gè)準(zhǔn)確的行高。

TextStyle(height: 1)

但是我們需要注意,每一種字體格式都定義了自己的字體度量默認(rèn)高度,這也是為什么即使設(shè)置了相同的字體高度,也會(huì)有不同的TextSpan的高度。

讓我們來看下這個(gè)例子:

紅色是Flutter默認(rèn)的字體,藍(lán)色是Bariol_Regular字體,綠色是Bellota-Regular字體,看看他們?cè)谙嗤?code>height下不同的框高度。

  • 默認(rèn)height

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-ikr2c80A-1669544494699)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6f47d0f38c7443b8bbaad4ac3e15cc04~tplv-k3u1fbpfcp-watermark.image?)]

  • height: 1.0

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-qe9aiK52-1669544494700)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fa54e9cf2b28475ea39155ede0583499~tplv-k3u1fbpfcp-watermark.image?)]

  • height:0.8

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-tbGTBpwJ-1669544494701)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1733f3d05cb2482fb868d92c7e14d8dc~tplv-k3u1fbpfcp-watermark.image?)]

這個(gè)例子也很好的驗(yàn)證了:

  • 即使使用一樣的fontSize,每種字體也都有不同的高度
  • 每一種字體都有不同的基線。

那么關(guān)于Flutter的字體組成我們也可以得到一個(gè)結(jié)論:使用多種字體大概率會(huì)因?yàn)榛€的不同導(dǎo)致布局不協(xié)調(diào)!

Flutter中是如何繪制文本的?

通過Paragraph,Flutter最后繪制文本時(shí)都是通過Paragraph完成的!

// Paragraph paragraph:文本對(duì)象
// Offset offset:文本繪制的位置
void drawParagraph(Paragraph paragraph, Offset offset)

舉個(gè)例子: 通過drawParagraph繪制一段文字

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-C7TkjSos-1669544494702)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fc53245c2bbd4a9c86207b2cf58afbfd~tplv-k3u1fbpfcp-watermark.image?)]

import 'dart:ui' as ui;
class TextPainter extends CustomPainter {
  //創(chuàng)建段落構(gòu)建器
  ParagraphBuilder paragraphBuilder = ParagraphBuilder(
      ParagraphStyle(fontWeight: FontWeight.bold, fontSize: 16))
    ..pushStyle(ui.TextStyle(color: Colors.black))
    ..addText('通過drawParagraph繪制的 Hello Taxze');
?
  @override
  void paint(Canvas canvas, Size size) {
    //設(shè)置段落寬度
    ParagraphConstraints paragraphConstraints =
        ParagraphConstraints(width: size.width);
    //計(jì)算繪制的文本位置及尺寸
    Paragraph paragraph = paragraphBuilder.build()
      ..layout(paragraphConstraints);
    //繪制
    canvas.drawParagraph(paragraph, const Offset(40.0, 50.0));
  }
?
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) =>false;
}

使用:

@override
Widget build(BuildContext context) {
  return Scaffold(
    ...
    body: SizedBox.expand(child: CustomPaint(painter: TextPainter())),
  );
}

SizedBox.expand包裹CustomPaint是為了給ParagraphConstraints(width: size.width)一個(gè)size。你也可以用其他的組件包裹它。

關(guān)于Flutter使用CustomPaint繪制文字的實(shí)踐較為復(fù)雜,若要講清楚繪制的主要知識(shí)點(diǎn),則需要另開一篇文章來講述。若對(duì)這個(gè)部分感興趣的朋友可以閱讀下這篇文章:Flutter學(xué)習(xí):使用CustomPaint繪制文字 — @菠蘿橙子丶

Flutter是如何把一段長(zhǎng)文字轉(zhuǎn)變成段落的?

你有沒有想過,F(xiàn)lutter是如何把一段長(zhǎng)文字生成下面的這樣一個(gè)段落的呢?

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-K8zsfS9R-1669544494703)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a6aa369fa78f4762b66bfa5f64026cee~tplv-k3u1fbpfcp-watermark.image?)]

這張效果圖的代碼:

Container(
    color: Colors.red,
    width: 200,
    height: 100,
    margin: EdgeInsets.all(30),
    child: Text(
        "通過drawParagraph繪制的 Taxze Hello....")),

那么其中的自動(dòng)換行是怎么實(shí)現(xiàn)的呢?

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-hQ2ezYSG-1669544494704)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a4fe3f2943234c1ca5372dc902c53b57~tplv-k3u1fbpfcp-watermark.image?)]
我們知道,段落指的就是一段文本,我們要給每個(gè)字符一個(gè)合適的大小和位置。那么Flutter是如何計(jì)算這些參數(shù)的呢?

在前文說到過,F(xiàn)lutter最后繪制文本時(shí)都是通過Paragraph完成的。Flutter就是通過Paragraph.layout來計(jì)算這些參數(shù),而且ParagraphBuilder給每個(gè)字符都在渲染前分配了一個(gè)偏移量。通過Paragraph可以知道所有占位符的位置和尺寸大小。

class TextPosition {
  //創(chuàng)建一個(gè)表示字符串中特定位置的對(duì)象。
  const TextPosition({
    required this.offset,
    this.affinity = TextAffinity.downstream,
  }) : assert(offset != null),
       assert(affinity != null);
  //舉個(gè)例子:有一個(gè)“Hello”字符,offset = 0表示光標(biāo)在字符H之前,offset = 5表示光標(biāo)在字符o之后。
  final int offset;
  final TextAffinity affinity;
?
  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType)
      return false;
    return other is TextPosition
        && other.offset == offset
        && other.affinity == affinity;
  }
?
  @override
  int get hashCode =>Object.hash(offset, affinity);
?
  @override
  String toString() {
    return 'TextPosition(offset: $offset, affinity: $affinity)';
  }
}
Text()背后的大哥有哪些?

–文本的渲染流程

從之前講述的知識(shí)點(diǎn),Text()組件它的build方法返回的就是RichText,但是Flutter最后繪制文本時(shí)又都是通過Paragraph完成的!那么其中的完整的一個(gè)流程是怎么樣的呢?話不多說,先上圖!

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-dDMUcy7t-1669544494704)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dbce4fff785640e78c6c743b6ed6c409~tplv-k3u1fbpfcp-watermark.image?)]

組件層

如圖所示,每當(dāng)我們使用Text組件時(shí),它實(shí)際上創(chuàng)建的是RichText組件。但是RichTextText不同的是,TextString作為參數(shù),而RichTextInlinSpan作為參數(shù)(或者說是TextSpan)。

const Text(String this.data)
    
//通過Text.rich構(gòu)造函數(shù)傳給RichText
const Text.rich(InlineSpan this.textSpan)
    
RichText(
      ...
      text: TextSpan(
        style: effectiveTextStyle,
        text: data,
        children: textSpan != null ?[textSpan!] : null,
      ),
)

//TextSpan繼承于InlineSpan
class TextSpan extends InlineSpan implements HitTestTarget, MouseTrackerAnnotation {}

RichText接收TextSpan,而每一個(gè)TextSpan都有更多的子TextSpan,這些子TextSpan會(huì) 繼承父TextSpan的樣式。例如:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-PF2spzd5-1669544494705)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/233e496530c94552aca073ef9b90a60c~tplv-k3u1fbpfcp-watermark.image?)]

RichText(
    text: TextSpan(
        style: Theme.of(context)
            .textTheme
            .bodyText1
            ?.copyWith(fontSize: 24),
        children: [
      TextSpan(
        text: 'Taxze ',
      ),
      TextSpan(text: 'blog', style: TextStyle(color: Colors.blue)),
      TextSpan(
        text: ' Flutter',
      ),
      TextSpan(text: '稀土掘金', style: TextStyle(color: Colors.blue)),
    ]))

不過,RichText本身是MultiChildRenderObjectWidget的子類。它們之間有這樣的繼承關(guān)系:

class RichText extends MultiChildRenderObjectWidget {}
abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {}

MultiChildRenderObjectWidget產(chǎn)生的MultiChildRenderObjectElement則是這樣的關(guān)系:

class MultiChildRenderObjectElement extends RenderObjectElement {}
abstract class RenderObjectElement extends Element {}

RichText實(shí)際上是需要一個(gè)InlineSpan,而InlineSpan可以是TextSpan或者是WidgetSpan。對(duì)WidgetSpan有興趣的朋友,可以參考官方的文檔WidgetSpan。

到這里為止,我們可以將RichText(包括RichText)之前的所有劃分為組件層,那么我們現(xiàn)在就要進(jìn)入渲染層了。

渲染層

我們已經(jīng)知道了RichText會(huì)創(chuàng)建一個(gè)渲染對(duì)象—RenderParagraph,那么RenderParagraph是干什么的呢?

RichTextMultiChildRenderObjectWidget的子類,它會(huì)把MultiChildRenderObjectElement往下傳遞,但是此時(shí)MultiChildRenderObjectElement沒有渲染,它還沒有什么作用。這個(gè)時(shí)候RichText會(huì)給它一個(gè)RenderParagraph,RenderParagraph會(huì)收到RenderPadding的指令,這個(gè)時(shí)候MultiChildRenderObjectElement就準(zhǔn)備好了一切,就可以開始工作了。

這樣解釋可能有點(diǎn)抽象,那么我們來看下這個(gè)例子:

body: Container(
            alignment: Alignment.center,
            child: Text("Taxze Hello"), ,
)

很簡(jiǎn)單的一個(gè)小例子,它的結(jié)構(gòu)也很清晰:

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-yhsYCYUC-1669544494705)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ef477b4af1b849f3a3cf5aa3f68c8466~tplv-k3u1fbpfcp-watermark.image?)]

當(dāng)Flutter把三棵樹都構(gòu)建完后:

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-zinkstt2-1669544494706)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/58bc0cb3d88a4dc1b08305026eef423a~tplv-k3u1fbpfcp-watermark.image?)]

那么當(dāng)我們改變文本時(shí),又會(huì)發(fā)生什么呢?

最先改變的當(dāng)然是組件層:

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-94R0jawX-1669544494706)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/313481d32f85479c8eb3dd8ffe47b545~tplv-k3u1fbpfcp-watermark.image?)]

我們會(huì)有一個(gè) “新” 的組件樹。不過你真的認(rèn)為都是新的嗎?Flutter會(huì)充分利用現(xiàn)有的元素,讓我們來看下這個(gè)名為canUpdate的方法吧。

static bool canUpdate(Widget oldWidget, Widget newWidget) {
  return oldWidget.runtimeType == newWidget.runtimeType
      && oldWidget.key == newWidget.key;
}

通過這個(gè)方法,F(xiàn)lutter可以檢查一個(gè)老的組件的Typekey,并把它和新的組件進(jìn)行比較。如果它們都相同的話,就不需要更新。

所以就算更新后,Container更新之后它還是存在的,而且我們沒有給它一個(gè)Key,所以OldContainerNewContainer是完全相同的。Align、Text、以及RichText它們的Type和Key都沒有變化,重新構(gòu)建它們沒有什么意義,所以它們都不會(huì)有更新。

到這里,我猜你肯定會(huì)問,都沒有更新,那么文本是如何改變的呢?

那么我們就要講到組件中的屬性了。組件除了具有Type和Key之外,還有屬性。屬性的改變會(huì)使RenderParagraph顯示新的文本。

不過關(guān)于文本的更改渲染到現(xiàn)在我們都是在紙上談兵,那么我們現(xiàn)在就來用一個(gè)簡(jiǎn)單的例子去驗(yàn)證之前的結(jié)論。

bool _isFirst = true;
?
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        floatingActionButton: FloatingActionButton(
          child: const Icon(Icons.swap_horiz),
          onPressed: () {
            setState(() {
              _isFirst = !_isFirst;
            });
          },
        ),
        body: _isFirst ? first() : second());
  }
}
?
Widget first() =>Container(
      alignment: Alignment.center,
      child: const Text("Taxze First"),
);
?
Widget second() =>Container(
      alignment: Alignment.center,
      child: const Text("Taxze Second"),
);

非常簡(jiǎn)單的一個(gè)例子,點(diǎn)擊按鈕更改顯示文字。當(dāng)我們點(diǎn)下按鈕時(shí),文本改變后,所有的組件都會(huì)重用,F(xiàn)lutter只會(huì)重建RenderPadding。

繪制層

在渲染層中,我們最后發(fā)生文本變化都在RenderParagraph上,不過RenderParagraph并不會(huì)直接的繪制文本,而是會(huì)創(chuàng)建一TextPainter來管理繪制的工作。

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-JgUMZp4Z-1669544494706)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f358e123221c48ef8891ea7a5ef49620~tplv-k3u1fbpfcp-watermark.image?)]
不過,TextPainter做的事和它的名字完全不一樣,你以為就是它來繪制文本的嗎?No~

實(shí)際上,它只是負(fù)責(zé)管理繪制的事,但它自己不會(huì)去繪制(當(dāng)老板)。

基礎(chǔ)層

到現(xiàn)在為止,你會(huì)發(fā)現(xiàn),講了那么多,但是還是沒有那個(gè)ta去真正的繪制文本,就好像之前的所有的組件都在當(dāng)中間商,把活外包了出去。

到了Flutter的最底層,你會(huì)發(fā)現(xiàn)有一個(gè)ParagraphBuilderParagraph,在前面關(guān)于Flutter如何繪制文本中,我們也提到了Flutter最后繪制文本時(shí)都是通過Paragraph完成的,而TextPainter是負(fù)責(zé)創(chuàng)建ParagraphBuilder的,但是當(dāng)你翻看Paragraph類的源碼時(shí),你會(huì)發(fā)現(xiàn),大部分的函數(shù)都是空函數(shù),原來這哥們也沒干活?。?/p>

@pragma('vm:entry-point')
class Paragraph extends NativeFieldWrapperClass1 {
  @pragma('vm:entry-point')
  Paragraph._();
?
  bool _needsLayout = true;
?
  double get width native 'Paragraph_width';
?
  double get height native 'Paragraph_height';
?
  double get longestLine native 'Paragraph_longestLine';
?
  double get minIntrinsicWidth native 'Paragraph_minIntrinsicWidth';
?
  double get maxIntrinsicWidth native 'Paragraph_maxIntrinsicWidth';
?
  double get alphabeticBaseline native 'Paragraph_alphabeticBaseline';
  ...
}

引擎層

當(dāng)ParagraphParagraphBuilder這兩個(gè)類都將繪制的工作交給了Flutter Engine后,我們也要將視線放到SkParagraph上了,在以前Flutter Engine處理文本繪制的庫(kù)是LibText。后面切換成了SkParagraph,但是也實(shí)現(xiàn)了和Libtext相同的API。對(duì)于Flutter引擎在這篇文章中只做一個(gè)簡(jiǎn)單的說明,若對(duì)引擎感興趣的朋友可以自己編譯FlutterEngine進(jìn)行學(xué)習(xí),或者在線閱讀。

–更詳細(xì)更深入的Flutter文本渲染原理有興趣的朋友可以閱讀這篇文章

解決Flutter文本基線不對(duì)齊的問題

經(jīng)常在各大Flutter交流群中看到有哥們問這樣的問題:Row中,兩個(gè)文本沒有對(duì)齊,這怎么處理呀?

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-jLL0YCuo-1669544494707)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/327583bd15264122a5b1e9c4bc2c0aca~tplv-k3u1fbpfcp-watermark.image?)]
展示圖代碼:

Center(
  child: Row(
    children: [
      ColoredBox(
        color: Colors.amber,
        child: Text.rich(TextSpan(children: [
          TextSpan(text: "¥999", style: TextStyle(fontSize: 28)),
          TextSpan(text: ".9", style: TextStyle(fontSize: 14)),
        ])),
      ),
      ColoredBox(
        color: Colors.red,
        child: Text.rich(TextSpan(children: [
          TextSpan(text: "123", style: TextStyle(fontSize: 12)),
        ])),
      ),
    ],
  ),
)

其實(shí)處理這個(gè)問題很簡(jiǎn)單,只需要給Row加上:

textBaseline: TextBaseline.alphabetic,
crossAxisAlignment: CrossAxisAlignment.baseline,

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-JFwhozn4-1669544494707)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/add602d2e218444e8ccf7c3f157b108b~tplv-k3u1fbpfcp-watermark.image?)]

關(guān)于更多有關(guān)文本的布局問題大家可以查看官方這篇文檔。

尾述

在這篇文章中,我們知道了文本是由什么組成的,F(xiàn)lutter是怎樣將文本顯示到屏幕上的。但是這也只是Flutter關(guān)于文本的一小部分,關(guān)于文本的編輯…等內(nèi)容將會(huì)在后續(xù)的文章中繼續(xù)探索。希望這篇文章能對(duì)你有所幫助,有問題歡迎在評(píng)論區(qū)留言討論~

參考&推薦閱讀

Flutter Text Rendering — @Jonathan Sande

書后拓展:Flutter 中一行文字到屏幕上,渲染全過程! — @MeandNi

Flutter 小技巧之玩轉(zhuǎn)字體渲染和問題修復(fù) — @戀貓de小郭

Flutter學(xué)習(xí):使用CustomPaint繪制文字 — @菠蘿橙子丶

關(guān)于我

Hello,我是Taxze,如果您覺得文章對(duì)您有價(jià)值,希望您能給我的文章點(diǎn)個(gè)??,有問題需要聯(lián)系我的話:我在這里

如果您覺得文章還差了那么點(diǎn)東西,也請(qǐng)通過關(guān)注督促我寫出更好的文章——萬(wàn)一哪天我進(jìn)步了呢?😝

— 文字是人類用符號(hào)記錄表達(dá)信息以傳之久遠(yuǎn)的方式和工具。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

當(dāng)前名稱:Flutter中那些你需要知道的文本知識(shí)!-創(chuàng)新互聯(lián)
文章來源:http://chinadenli.net/article40/djjgho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、關(guān)鍵詞優(yōu)化、小程序開發(fā)、網(wǎng)站建設(shè)、網(wǎng)站策劃、網(wǎng)站維護(hù)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)
五月天婷亚洲天婷综合网| 日本精品免费在线观看| 欧美一区二区黑人在线| 日本不卡在线一区二区三区| 日韩不卡一区二区在线| 国产乱人伦精品一区二区三区四区| 美女露小粉嫩91精品久久久| av免费视屏在线观看| 在线视频免费看你懂的| 免费观看在线午夜视频| 99久久人妻精品免费一区| 国产精品色热综合在线| 国产精品午夜福利免费阅读| 中文字幕日韩无套内射| 久久综合亚洲精品蜜桃| 亚洲少妇人妻一区二区| 国产福利一区二区三区四区| 欧美一区二区口爆吞精| 日韩成人动作片在线观看| 日韩中文字幕视频在线高清版 | 久久精品国产在热亚洲| 神马午夜福利一区二区| 亚洲清纯一区二区三区| 色无极东京热男人的天堂| 国产高清一区二区白浆| 亚洲视频偷拍福利来袭| 欧美亚洲91在线视频| 老熟妇2久久国内精品| 亚洲一区二区精品国产av| 精产国品一二三区麻豆| 亚洲国产婷婷六月丁香| 亚洲精品偷拍一区二区三区| 国产欧美性成人精品午夜| 好吊日视频这里都是精品| 一本色道久久综合狠狠躁| 清纯少妇被捅到高潮免费观看| 99秋霞在线观看视频| 99久只有精品免费视频播放| 大香蕉精品视频一区二区| 老熟女露脸一二三四区| 精品久久综合日本欧美|