国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Flutter 筆記 | Flutter 核心原理(三)布局(Layout )過程

這篇具有很好參考價(jià)值的文章主要介紹了Flutter 筆記 | Flutter 核心原理(三)布局(Layout )過程。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

布局過程

Layout(布局)過程主要是確定每一個(gè)組件的布局信息(大小和位置),F(xiàn)lutter 的布局過程如下:

  1. 父節(jié)點(diǎn)向子節(jié)點(diǎn)傳遞約束(constraints)信息,限制子節(jié)點(diǎn)的最大和最小寬高。
  2. 子節(jié)點(diǎn)根據(jù)約束信息確定自己的大小(size)。
  3. 父節(jié)點(diǎn)根據(jù)特定布局規(guī)則(不同布局組件會有不同的布局算法)確定每一個(gè)子節(jié)點(diǎn)在父節(jié)點(diǎn)布局空間中的位置,用偏移 offset 表示。
  4. 遞歸整個(gè)過程,確定出每一個(gè)節(jié)點(diǎn)的大小和位置。

可以看到,組件的大小是由自身決定的,而組件的位置是由父組件決定的。

下面是官網(wǎng)的一張圖,它用三句話描述了 Flutter 布局過程的精髓:

Flutter 筆記 | Flutter 核心原理(三)布局(Layout )過程

Flutter 中的布局類組件很多,根據(jù)孩子數(shù)量可以分為單子組件和多子組件,下面我們先通過分別自定義一個(gè)單子組件和多子組件來直觀理解一下Flutter的布局過程,之后會介紹一下布局更新過程和 Flutter 中的 Constraints(約束)。

單子組件布局示例

我們實(shí)現(xiàn)一個(gè)單子組件 CustomCenter,功能基本和 Center 組件對齊,通過這個(gè)實(shí)例我們演示一下布局的主要流程。

首先,我們定義組件,為了介紹布局原理,我們不采用組合的方式來實(shí)現(xiàn)組件,而是直接通過定制 RenderObject 的方式來實(shí)現(xiàn)。因?yàn)榫又薪M件需要包含一個(gè)子節(jié)點(diǎn),所以我們直接繼承 SingleChildRenderObjectWidget。

class CustomCenter extends SingleChildRenderObjectWidget {
   
  const CustomCenter2({
   Key? key, required Widget child})
      : super(key: key, child: child);

  
  RenderObject createRenderObject(BuildContext context) {
   
    return RenderCustomCenter();
  }
}

接著實(shí)現(xiàn) RenderCustomCenter。這里直接繼承 RenderObject 會更接近底層一點(diǎn),但這需要我們自己手動實(shí)現(xiàn)一些和布局無關(guān)的東西,比如事件分發(fā)等邏輯。為了更聚焦布局本身,我們選擇繼承自RenderShiftedBox,它是RenderBox的子類(RenderBox繼承自RenderObject),它會幫我們實(shí)現(xiàn)布局之外的一些功能,這樣我們只需要重寫performLayout,在該函數(shù)中實(shí)現(xiàn)子節(jié)點(diǎn)居中算法即可。

class RenderCustomCenter extends RenderShiftedBox {
   
  RenderCustomCenter({
   RenderBox? child}) : super(child);

  
  void performLayout() {
   
    //1. 先對子組件進(jìn)行l(wèi)ayout,隨后獲取它的size
    child!.layout(
      constraints.loosen(), //將約束傳遞給子節(jié)點(diǎn)
      parentUsesSize: true, // 因?yàn)槲覀兘酉聛硪褂胏hild的size,所以不能為false
    );
    //2.根據(jù)子組件的大小確定自身的大小
    size = constraints.constrain(Size(
      constraints.maxWidth == double.infinity
          ? child!.size.width
          : double.infinity,
      constraints.maxHeight == double.infinity
          ? child!.size.height
          : double.infinity,
    ));

    // 3. 根據(jù)父節(jié)點(diǎn)子節(jié)點(diǎn)的大小,算出子節(jié)點(diǎn)在父節(jié)點(diǎn)中居中之后的偏移,然后將這個(gè)偏移保存在
    // 子節(jié)點(diǎn)的parentData中,在后續(xù)的繪制階段,會用到。
    BoxParentData parentData = child!.parentData as BoxParentData;
    parentData.offset = ((size - child!.size) as Offset) / 2;
  }
}

布局過程請參考注釋,在此需要額外說明有3點(diǎn):

  1. 在對子節(jié)點(diǎn)進(jìn)行布局時(shí), constraintsCustomCenter 的父組件傳遞給自己的約束信息,我們傳遞給子節(jié)點(diǎn)的約束信息是constraints.loosen(),下面看一下loosen的實(shí)現(xiàn)源碼:
BoxConstraints loosen() {
   
  return BoxConstraints(
    minWidth: 0.0,
    maxWidth: maxWidth,
    minHeight: 0.0,
    maxHeight: maxHeight,
  );
}

很明顯,CustomCenter 約束子節(jié)點(diǎn)最大寬高不超過自身的最大寬高。

  1. 子節(jié)點(diǎn)在父節(jié)點(diǎn)(CustomCenter)的約束下,確定自己的寬高;此時(shí)CustomCenter會根據(jù)子節(jié)點(diǎn)的寬高確定自己的寬高,上面代碼的邏輯是,如果CustomCenter父節(jié)點(diǎn)傳遞給它最大寬高約束是無限大時(shí),它的寬高會設(shè)置為它子節(jié)點(diǎn)的寬高。注意,如果這時(shí)將CustomCenter的寬高也設(shè)置為無限大就會有問題,因?yàn)樵谝粋€(gè)無限大的范圍內(nèi)自己的寬高也是無限大的話,那么實(shí)際上的寬高到底是多大,它的父節(jié)點(diǎn)會懵逼的!屏幕的大小是固定的,這顯然不合理。如果CustomCenter父節(jié)點(diǎn)傳遞給它的最大寬高約束不是無限大,那么是可以指定自己的寬高為無限大的,因?yàn)樵谝粋€(gè)有限的空間內(nèi),子節(jié)點(diǎn)如果說自己無限大,那么最大也就是父節(jié)點(diǎn)的大小。所以,簡而言之,CustomCenter 會盡可能讓自己填滿父元素的空間。

  2. CustomCenter 確定了自己的大小和子節(jié)點(diǎn)大小之后就可以確定子節(jié)點(diǎn)的位置了,根據(jù)居中算法,將子節(jié)點(diǎn)的原點(diǎn)坐標(biāo)算出后保存在子節(jié)點(diǎn)的 parentData 中,在后續(xù)的繪制階段會用到,具體怎么用,我們看一下RenderShiftedBox中默認(rèn)的 paint 實(shí)現(xiàn):


void paint(PaintingContext context, Offset offset) {
   
  if (child != null) {
   
    final BoxParentData childParentData = child!.parentData! as BoxParentData;
    //從child.parentData中取出子節(jié)點(diǎn)相對當(dāng)前節(jié)點(diǎn)的偏移,加上當(dāng)前節(jié)點(diǎn)在屏幕中的偏移,
    //便是子節(jié)點(diǎn)在屏幕中的偏移。
    context.paintChild(child!, childParentData.offset + offset);
  }
}
performLayout 流程

可以看到,布局的邏輯是在 performLayout 方法中實(shí)現(xiàn)的。我們梳理一下 performLayout 中具體做的事:

  1. 如果有子組件,則對子組件進(jìn)行遞歸布局。
  2. 確定當(dāng)前組件的大小(size),通常會依賴子組件的大小。
  3. 確定子組件在當(dāng)前組件中的起始偏移。

在Flutter組件庫中,有一些常用的單子組件比如 Align、SizedBox、DecoratedBox 等,都可以打開源碼去看看其實(shí)現(xiàn)。

下面我們看一個(gè)多子組件的例子。

多子組件布局示例

實(shí)際開發(fā)中我們會經(jīng)常用到貼邊左-右布局,現(xiàn)在我們就來實(shí)現(xiàn)一個(gè) LeftRightBox 組件來實(shí)現(xiàn)左-右布局,因?yàn)?code>LeftRightBox 有兩個(gè)孩子,用一個(gè) Widget 數(shù)組來保存子組件。

首先我們定義組件,與單子組件不同的是多子組件需要繼承自 MultiChildRenderObjectWidget

lass LeftRightBox extends MultiChildRenderObjectWidget {
   
  LeftRightBox({
   
    Key? key,
    required List<Widget> children,
  })  : assert(children.length == 2, "只能傳兩個(gè)children"),
        super(key: key, children: children);

  
  RenderObject createRenderObject(BuildContext context) {
   
    return RenderLeftRight();
  }
}

接下來需要實(shí)現(xiàn) RenderLeftRight,在其 performLayout 中我們實(shí)現(xiàn)實(shí)現(xiàn)左-右布局算法:文章來源地址http://www.zghlxwxcb.cn/news/detail-485222.html

class LeftRightParentData extends ContainerBoxParentData<RenderBox> {
   }

class RenderLeftRight extends RenderBox
    with
        ContainerRenderObjectMixin<RenderBox, LeftRightParentData>,
        RenderBoxContainerDefaultsMixin<RenderBox, LeftRightParentData> {
   
 
  // 初始化每一個(gè)child的parentData        
  
  void setupParentData(RenderBox child) {
   
    if (child.parentData is! LeftRightParentData)
      child.parentData = LeftRightParentData();
  }

  
  void performLayout() {
   
    final BoxConstraints constraints = this.constraints;
    RenderBox leftChild = firstChild!;
    
    LeftRightParentData childParentData =
        leftChild.parentData! as LeftRightParentData;
    
    RenderBox rightChild = childParentData.nextSibling!;

    //我們限制右孩子寬度不超過總寬度一半
    rightChild.layout(
      constraints.copyWith(maxWidth: constraints.maxWidth / 2),
      parentUsesSize

到了這里,關(guān)于Flutter 筆記 | Flutter 核心原理(三)布局(Layout )過程的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • RPC核心原理(整體架構(gòu)/調(diào)用過程)

    RPC核心原理(整體架構(gòu)/調(diào)用過程)

    Server: Provider ,暴露服務(wù),服務(wù)提供方 Client: Consumer ,服務(wù)消費(fèi),調(diào)用遠(yuǎn)程服務(wù) Registry:服務(wù)注冊與發(fā)現(xiàn) RPC的調(diào)用過程如下: 第一步:server會將他需要暴露的服務(wù)以及他的地址信息注冊到Registry這一注冊中心。 第二步:client通過注冊中心一只關(guān)注它所需要的服務(wù)在哪里,如果此時(shí)

    2024年02月09日
    瀏覽(23)
  • 彈性盒子布局 Flexbox Layout

    彈性盒子布局 Flexbox Layout

    可以嵌套下去 1.display 屬性 默認(rèn)行排列 此時(shí)是 列拍 flex-direction屬性——行布局 row 列布局:column flex-wrap 屬性 折疊 flex-flow屬性 包括 flex-direction 和flex-wrap flex-flow: row wrap 行排列 折疊 justify-content屬性 元素在主軸上的對齊方式 左對齊 居中對齊 右對齊 兩端對齊 拉手對齊 align

    2024年03月15日
    瀏覽(21)
  • Qt入門教程【Core篇】Layout布局(布局管理器、手動布局)

    Qt入門教程【Core篇】Layout布局(布局管理器、手動布局)

    ?? 「CSDN主頁」 :傳送門 ?? 「Bilibil首頁」 :傳送門 ?? 「網(wǎng)易云課堂」 :傳送門 ?? 「CSDN學(xué)院」 :傳送門 ?? 「51CTO學(xué)院」 :傳送門 ?? 「本文的內(nèi)容」 :Qt布局指南 ?? 「動動你的小手」 : 點(diǎn)贊 ?? 收藏 ?? 評論 ?? 界面開發(fā)首先要對整個(gè)界面進(jìn)行布局,使窗體上

    2023年04月18日
    瀏覽(25)
  • HTML布局(HTML Layout)簡介

    HTML布局(HTML Layout)簡介

    HTML布局(HTML Layout)簡介 HTML布局(HTML Layout)是創(chuàng)建一個(gè)網(wǎng)站時(shí)需要考慮的情況,合理設(shè)計(jì)網(wǎng)頁中內(nèi)容的排列方式,讓網(wǎng)頁看起來更加合理、美觀,能產(chǎn)生引人注目的視覺效果。頁面布局一般包括: 標(biāo)題:前端的一部分,用于頁面頂部。header標(biāo)簽用于在網(wǎng)頁中添加標(biāo)題部分

    2024年02月08日
    瀏覽(14)
  • 【CocosCreator入門】CocosCreator組件 | Layout(布局)組件

    【CocosCreator入門】CocosCreator組件 | Layout(布局)組件

    ??????? Cocos Creator 是一款流行的游戲開發(fā)引擎,具有豐富的組件和工具,其中的Layout組件是一種用于實(shí)現(xiàn)節(jié)點(diǎn)自適應(yīng)布局的重要組件。它可以根據(jù)不同的布局方式,自動調(diào)整子節(jié)點(diǎn)的位置和大小,從而實(shí)現(xiàn)節(jié)點(diǎn)的自適應(yīng)布局。 目錄 一、組件介紹 二、組件屬性 三、布局類

    2023年04月22日
    瀏覽(16)
  • Unity 網(wǎng)格布局控件-Grid Layout Group

    Unity 網(wǎng)格布局控件-Grid Layout Group

    Unity 網(wǎng)格布局控件-Grid Layout Group是Unity中的UGUI控件,用于在 UI 中創(chuàng)建網(wǎng)格布局, 它的作用是:自動將子對象排列成網(wǎng)格,即我們可以通過該組件對子對象按行和列的形式排列,根據(jù)指定的約束條件自動調(diào)整它們的大小和位置。通常我們使用它創(chuàng)建具有規(guī)律排列的 UI 元素,如

    2024年02月04日
    瀏覽(17)
  • 【CSS 20】website layout 網(wǎng)站布局 頁眉 導(dǎo)航欄 列布局 不相等欄 頁腳

    website layout 網(wǎng)站布局 header 頁眉 頁眉(header)通常位于網(wǎng)站頂部(或頂部導(dǎo)航菜單的正下方) 通常包含徽標(biāo)(logo)或網(wǎng)站名稱 navbar 導(dǎo)航欄 導(dǎo)航欄包含鏈接列表,以幫助訪問者瀏覽您的網(wǎng)站 內(nèi)容 使用哪種布局通常取決于您的目標(biāo)用戶 最常見的布局是以下布局之一(或?qū)⑺?/p>

    2024年02月13日
    瀏覽(22)
  • 設(shè)置layout布局嵌套路由格式正確但是看不見頁面問題

    一定確保格式正確.試試重置component路徑 children: [

    2024年02月13日
    瀏覽(16)
  • 【ArcGIS Pro二次開發(fā)】(50):布局(Layout)的基本操作

    ArcGIS Pro SDK中的布局(Layout)是用于創(chuàng)建和編輯打印布局的一組功能。 Layout是打印布局的容器,它可以包含多個(gè)元素,例如地圖框、文本框、圖例、比例尺等。 Layout中包含多種元素,比較重要的有:地圖(MapFrameElement)、文本(TextElement)、圖片(PictureElement)、圖例(LegendElement)等。

    2024年02月16日
    瀏覽(26)
  • Solidity內(nèi)存布局介紹 Layout in Memory and Storage

    Solidity reserves four 32-byte slots, with specific byte ranges (inclusive of endpoints) being used as follows: 0x00 - 0x3f (64 bytes): scratch space(暫存空間) for hashing methods? Hash方法的暫存空間. 0x40 - 0x5f (32 bytes): currently allocated memory size (aka. free memory pointer) 0x60 - 0x7f (32 bytes): zero slot Solidity保留了四個(gè)32字節(jié)的

    2024年02月16日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包