【Flutter 專題】68 圖解基本約束 Box (三)|8月更文挑戰

阿策小和尚發表於2021-08-20

      “這是我參與8月更文挑戰的第20天,活動詳情檢視: 8月更文挑戰” juejin.cn/post/698796…

      小菜對約束 Box 探索之路還在繼續,小菜今天主要學習一下 Overflow 相關 Box

OverflowBox

原始碼分析

class OverflowBox extends SingleChildRenderObjectWidget {
  const OverflowBox({
    Key key,
    this.alignment = Alignment.center,  // 對齊方式
    this.minWidth,                      // 允許最小寬度
    this.maxWidth,                      // 允許最大寬度
    this.minHeight,                     // 允許最小高度
    this.maxHeight,                     // 允許最大高度
    Widget child,
  })
}
複製程式碼

      分析原始碼可得,OverflowBox 通過設定最大最小寬高對子 Widget 進行約束,且與父 Widget 相關,子 Widget 可能會溢位父 Widget

案例嘗試

      小菜通過如下幾種場景探索 OverflowBox 與父 Widget 和子 Widget 的關聯關係,其中 alignment 是通用的對齊方式,不在此單獨說明;由於 OverflowBox 允許子 Widget 溢位父 Widget,很多朋友用此實現自定義 Dialog

  1. Widget 無約束,僅設定 minWidth / minHeight,子 Widget 寬高小於等於 OverflowBox 最小寬高;此時 child.width <= minWidth && child.height <= minHeight,最終以 OverflowBox 設定的最小寬高約束子 Widget
return Container(color: Colors.blueAccent.withOpacity(0.4),
    child: OverflowBox(alignment: Alignment.center, minHeight: 100,
        child: Container(color: Colors.purple.withOpacity(0.4), width: 50, height: 50)));
複製程式碼

  1. Widget 無約束,僅設定 minWidth / minHeight,子 Widget 寬高大於 OverflowBox 最小寬高;此時 minWidth < child.width < maxWidth,最終以子 Widget 設定的寬高展示;
 return Container(color: Colors.green.withOpacity(0.4),
    child: OverflowBox(alignment: Alignment.center, minHeight: 100, minWidth: 100,
        child:Container(color: Colors.purple.withOpacity(0.4), width: 150, height: 150)));
複製程式碼

  1. Widget 無約束,設定 maxWidth / maxHeight,若 child.width > maxWidth || child.height > maxHeight 則以 OverflowBox 設定的最大寬高約束子 Widget;若 child.width < maxWidth && child.height < maxHeight 則按照上述兩種情況進行約束;
return Container(color: Colors.orange.withOpacity(0.4),
    child: OverflowBox(alignment: Alignment.center,
        minHeight: 100, maxWidth: 150, maxHeight: 150,
        child: Container(color: Colors.purple.withOpacity(0.4), width: 50, height: 50)));
return Container(color: Colors.grey.withOpacity(0.4),
    child: OverflowBox(alignment: Alignment.center,
        minHeight: 100, minWidth: 100, maxWidth: 150, maxHeight: 150,
        child: Container(color: Colors.purple.withOpacity(0.4), width: 200, height: 200)));
複製程式碼

  1. Widget 有約束,設定 maxWidth > parent.width || maxHeight > parent.height,此時允許子 Widget 寬高大於父 Widget 寬高,其約束方式與上述情況相同;
return Container(width: 200, height: 200, color: Colors.brown.withOpacity(0.4),
    child: OverflowBox(alignment: Alignment.center,
        minHeight: 100, minWidth: 50, maxHeight: 250, maxWidth: 250,
        child: Container(color: Colors.purple.withOpacity(0.4))));
複製程式碼

  1. 對於大部分涉及最大最小寬高的 Widget,最小寬高均不允許大於最大寬高,使用時請注意;
return Container(width: 200, height: 200, color: Colors.brown.withOpacity(0.4),
    child: OverflowBox(alignment: Alignment.center,
        minHeight: 250, minWidth: 50,
        child: Container(color: Colors.purple.withOpacity(0.4))));
複製程式碼

SizedOverflowBox

原始碼分析

class SizedOverflowBox extends SingleChildRenderObjectWidget {
  const SizedOverflowBox({
    Key key,
    @required this.size,                // 約束 Size
    this.alignment = Alignment.center,  // 對齊方式
    Widget child,
  })
}
複製程式碼

      分析原始碼可知,SizedOverflowBoxSizedBoxOverflowBox 的結合,小菜簡單理解 SizedBox 設定基本約束,OverflowBox 設定子 Widget 與父 Widget 關係,是否溢位;

案例嘗試

      size 是對子 Widget 的基本尺寸約束,alignment 是通用的對齊方式,小菜按如下場景進行嘗試;

  1. Widget 無約束,若 child.width <= Size.x && child.height <= Size.y,以子 Widget 寬高約束展示;
return Container(color: Colors.green.withOpacity(0.4),
    child: Center(child: SizedOverflowBox(
        size: Size(100, 100), alignment: Alignment.center,
        child: Container(width: 50, height: 50, color: Colors.blueAccent.withOpacity(0.6)))));
複製程式碼

  1. Widget 無約束,若 child.width > Size.x || child.height > Size.h,以子 Widget 寬高溢位展示;
return Container(color: Colors.orange.withOpacity(0.4),
    child: Center(child: SizedOverflowBox(
        size: Size(100, 100), alignment: Alignment.center,
        child: Container(width: 150, height: 150, color: Colors.purple.withOpacity(0.4)))));
複製程式碼

  1. Widget 有約束時,若 child.width <= Size.x && child.height <= Size.y 時,與狀況一相同;若 child.width > parent.width >= Size.x || child.height > parent.height >= Size.y,則子 Widget 溢位 SizedOverflowBox 到父 Widget 約束寬高展示;
return Container(width: 150, height: 150, color: Colors.redAccent.withOpacity(0.4),
    child: Center(child: SizedOverflowBox(
        size: Size(100, 100), alignment: Alignment.center,
        child: Container(width: 250, height: 50, color: Colors.grey.withOpacity(0.8)))));
複製程式碼

  1. Widget 有約束時,若 Size.x > parent.width || Size.y > parent.height,最終展示的最大寬高是父 Widget 約束的寬高(子 Widget 溢位或非溢位);
return Container(width: 150, height: 150, color: Colors.redAccent.withOpacity(0.4),
    child: Center(child: SizedOverflowBox(
        size: Size(400, 400), alignment: Alignment.topLeft,
        child: Container(width: 150, height: 50, color: Colors.grey.withOpacity(0.8)))));
複製程式碼

小理解

      小菜嘗試了諸多約束 Box,甚至有些 Box 在使用和功能上大同小異,相同的功能,可以用其他的 Widget 來實現但為什麼要有這麼多約束 Box

      小菜對此理解還不夠深入,僅簡單的交流個人理解,如有錯誤請多多指導!對於常用的 SizedBox 既可以用作約束盒子也可以作為空間佔位符,對此 Container 完全可以實現,還可以實現很多複雜效果;SizedBox 存在的理由:小菜認為一是 SizedBox 功能更單一,相對於 Container 效能更好(Flutter 渲染效能很高,可以忽略不計);二是 SizedBox 功能性更加清晰明確;合理利用各 Widget 會讓編碼更加清晰高效;


      小菜對約束 Box 的探索暫時到此,希望大家可以對各類 Box 多多嘗試!

來源: 阿策小和尚

相關文章