【Flutter 元件集錄】SizedOverflowBox | 8 月更文挑戰

張風捷特烈發表於2021-08-26
前言:

這是我參與8月更文挑戰的第 26 天,活動詳情檢視:8月更文挑戰。為應掘金的八月更文挑戰,我準備在本月挑選 31 個以前沒有介紹過的元件,進行全面分析和屬性介紹。這些文章將來會作為 Flutter 元件集錄 的重要素材。希望可以堅持下去,你的支援將是我最大的動力~

本系列元件文章列表
1.NotificationListener2.Dismissible3.Switch
4.Scrollbar5.ClipPath6.CupertinoActivityIndicator
7.Opacity8.FadeTransition9. AnimatedOpacity
10. FadeInImage11. Offstage12. TickerMode
13. Visibility14. Padding15. AnimatedContainer
16.CircleAvatar17.PhysicalShape18.Divider
19.Flexible、Expanded 和 Spacer 20.Card21.SizedBox
22.ConstrainedBox23.Stack24.Positioned
25.OverflowBox26.SizedOverflowBox

1.認識 SizedOverflowBox 元件

從原始碼的介紹中可以看出 SizedOverflowBox 元件的特點是:

    1. 它可以指定自身特定的尺寸
    1. 它會將原始的約束傳遞給孩子
    1. 它的孩子可以溢位

上一篇介紹的 OverflowBox 元件也可以允許子元件溢位,他們最大的區別在於: OverflowBox 會指定新約束傳遞給孩子,而 SizedOverflowBox 則將原始約束傳遞給孩子。


下面是 SizedOverflowBox 元件類的定義構造方法,可以看出它繼承自 SingleChildRenderObjectWidget 。構造時必須傳入尺寸 size 引數,並且可以指定對齊方式。


2.SizedOverflowBox 元件的使用

如下,在一個灰色盒子左上角,有一個小紅圈,其中心與盒子左上角對齊。可以看出在效果上,小紅圈 溢位了灰色盒子的區域。實現方式是,灰色盒子內部對齊方式 Alignment.topLeftSizedOverflowBox 對齊方式 Alignment.center

class CustomSizedOverflowBox extends StatelessWidget{
  
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.topLeft,
      color: Colors.grey.withAlpha(88),
      width: 50,
      height: 50,
      child: buildChild(),
    );
  }

  Widget buildChild() {
    return SizedOverflowBox(
      alignment: Alignment.center,
      size: Size.zero,
      child: Container(
        decoration: const BoxDecoration(
          color: Colors.red,
          shape: BoxShape.circle,
        ),
        width: 15,
        height: 15,
      ),
    );
  }
}
複製程式碼

通過佈局可以檢視 SizedOverflowBox 的區域資訊,如下為 Size(0,0),也就是構造時我們傳入的尺寸。


size 設定為 Size(30,25) 時,效果如下。可見指定的尺寸值就是 SizedOverflowBox 的尺寸,而 SizedOverflowBoxalignment 屬性就是其內部的對齊方式。

SizedOverflowBox(
  alignment: Alignment.center,
  size: Size(30,25),
  //略同...
);
複製程式碼


下面是 SizedOverflowBox#alignmentAlignment.topLeft 的效果,可以看出小紅球在與左上角對齊。這就是 SizedOverflowBoxalignmentsize 兩個屬性的作用。

SizedOverflowBox(
  alignment: Alignment.topLeft,
  size: Size(30,25),
  //略同...
);
複製程式碼


3. SizedOverflowBox 約束分析

首先 SizedOverflowBox 會受父級的約束,比如上面的 Container 會施加 [w(50,50) - h(50,50)]的緊約束,但由於設定了 Container#alignment 屬性,內部會使用 Align 元件。這會讓 SizedOverflowBox 的約束變為了 [w(0,50) - h(0,50)] 的鬆散約束,此時 SizedOverflowBox 申請的尺寸為 30*25 ,滿足約束,則其尺寸為 30*25


如果去除了 Container#alignment 屬性, [w(50,50) - h(50,50)] 的強約束會直接施加到 SizedOverflowBox 上,即使申請的尺寸為 30*25 ,其尺寸也會變為 50*50。這也間接可以產出 Align 元件可以起到鬆散約束的效果。


SizedOverflowBox 的特點是:它的約束會直接傳遞給孩子,不做任何改動。可以看出 Align 施加給 SizedOverflowBox[w(0,50) - h(0,50)] 鬆散約束,會直接傳給小紅點。也就是說,雖然小紅點可以越界,但它的尺寸仍會受到外層的約束。

SizedOverflowBox 會將自身受到的約束,直接傳遞給孩子,這也能解釋為什麼去除了 Container#alignment 屬性,SizedOverflowBox 尺寸為 50*50小紅點尺寸也是 50*50


即使小紅點尺寸申請為 150*150,由於 [w(0,50) - h(0,50)] 的約束,自身尺寸也將被限制。


4.SizedOverflowBox 原始碼實現

SizedOverflowBox 繼承自 SingleChildRenderObjectWidget ,內部維護 RenderSizedOverflowBox 渲染物件來實現功能。


可以看出入參的尺寸會為 _requestedSize 屬性賦值。

performLayout 中,通過當前約束請求尺寸,來決定 RenderSizedOverflowBox 的尺寸。這個渲染物件非常特別,一般來說都是約束x 向下傳遞給子節點進行佈局,之後子節點向上反饋尺寸。而這裡是先確定父節點的尺寸,也就表明它的尺寸並不受子渲染物件影響。如果 child 非空,會對自渲染物件進行佈局,傳入的是自身的原始約束

那本文到這裡就結束了,謝謝觀看,明天見~

相關文章