天天看點

Flutter 67: 圖解基本限制 Box (二)

      小菜繼續學習限制 Box 的各類應用;

UnconstrainedBox

源碼分析

class UnconstrainedBox extends SingleChildRenderObjectWidget {
    const UnconstrainedBox({
        Key key,
        Widget child,
        this.textDirection,                 // 文字方向
        this.alignment = Alignment.center,  // 對齊方式
        this.constrainedAxis,               // 是否保留限制軸方向
    })
}           

      分析源碼可得,UnconstrainedBox 繼承自 SingleChildRenderObjectWidget,與 ConstrainedBox 效果相反,給子 Widget 提供不加限制的空間;

案例嘗試

      UnconstrainedBox 不會對子 Widget 進行限制限制,按照其子 Widget 大小進行繪制;小菜了解為去除父 Widget 的限制,讓子 Widget 完全繪制;

1. alignment

      用于子 Widget 的對齊方向,可以通過 Alignment 或 AlignmentDirectional 進行調整所在位置;其中 AlignmentDirectional start/y 範圍是 [-1.0, 1.0];

2. textDirection

      當 alignment 使用 AlignmentDirectional 方式設定對齊方式時,textDirection 用于從左到右或從右到左的起始方向;

return Container(height: 180, width: 180, color: Colors.blueAccent.withOpacity(0.4),
    child: UnconstrainedBox(constrainedAxis: null,
        alignment: AlignmentDirectional(-1.0, 1.0), textDirection: TextDirection.ltr, 
        child: Container(width: 90, height: 90, color: Colors.green.withOpacity(0.6))));
return Container(height: 180, width: 180, color: Colors.redAccent.withOpacity(0.4),
    child: UnconstrainedBox(constrainedAxis: null,
        alignment: AlignmentDirectional(-1.0, -1.0), textDirection: TextDirection.rtl,
        child: Container(width: 100, height: 100, color: Colors.purple.withOpacity(0.6))));           
Flutter 67: 圖解基本限制 Box (二)
3. constrainedAxis

      作用于是否保留限制的軸方向,若不設定或設定為 null 則橫向或縱向均不保留限制;若設定為 vertical 則保留其父類縱向限制;設定為 horizontal 則保留其父類橫向限制;

return Container(height: 100, width: 360, color: Colors.blueAccent.withOpacity(0.4),
    child: UnconstrainedBox(alignment: Alignment.center, constrainedAxis: null,
        child: Container(width: 80, height: 80, color: Colors.green.withOpacity(0.6))));
return Container(height: 100, width: 360, color: Colors.blueAccent.withOpacity(0.4),
    child: UnconstrainedBox(alignment: Alignment.center, constrainedAxis: Axis.vertical,
        child: Container(width: 100, height: 300, color: Colors.green.withOpacity(0.6))));
return Container(height: 100, width: 360, color: Colors.blueAccent.withOpacity(0.4),
    child: UnconstrainedBox(alignment: Alignment.topRight, constrainedAxis: Axis.horizontal,
        child: Container(width: 100, height: 300, color: Colors.green.withOpacity(0.6))));
return Container(height: 100, width: 360, color: Colors.blueAccent.withOpacity(0.4),
    child: UnconstrainedBox(alignment: Alignment.topLeft, constrainedAxis: null,
        child: Container(width: 100, height: 300, color: Colors.green.withOpacity(0.6))));           
Flutter 67: 圖解基本限制 Box (二)

LimitedBox

class LimitedBox extends SingleChildRenderObjectWidget {
  const LimitedBox({
    Key key,
    this.maxWidth = double.infinity,    // 最大寬度
    this.maxHeight = double.infinity,   // 最大高度
    Widget child,
  })
}           

      分析源碼可知,LimitedBox 主要是在不受父 Widget 限制時,通過 maxHeight / maxWidth 對子 Widget 的限制,且 maxHeight / maxWidth 必須 >= 0.0;

      小菜分如下幾個場景進行嘗試

  1. LimitedBox 父 Widget 無限制,子 Widget 寬高小于限制最大寬高;
return Container(child: LimitedBox(maxWidth: 100, maxHeight: 100, child: Container(width: 80, height: 80, color: Colors.purple.withOpacity(0.4))));           
Flutter 67: 圖解基本限制 Box (二)
  1. LimitedBox 父 Widget 無限制,子 Widget 寬高大于限制最大寬高;
return Container(child: LimitedBox(maxWidth: 100, maxHeight: 100, child: Container(width: 160, height: 160, color: Colors.orange.withOpacity(0.4))));           
Flutter 67: 圖解基本限制 Box (二)
  1. LimitedBox 父 Widget 有限制時;無論 LimitedBox 設定限制最大寬高和子 Widget 寬高,均以父 Widget 寬高為準;
return Container(width: 200, height: 80, child: LimitedBox(maxWidth: 100, maxHeight: 100, child: Container(width: 160, height: 160, color: Colors.orange.withOpacity(0.4))));           
Flutter 67: 圖解基本限制 Box (二)

FractionallySizedBox

class FractionallySizedBox extends SingleChildRenderObjectWidget {
  const FractionallySizedBox({
    Key key,
    this.alignment = Alignment.center,  // 對齊方式
    this.widthFactor,                   // 寬度因子
    this.heightFactor,                  // 高度因子
    Widget child,
  })
}           

      分析源碼可知,FractionallySizedBox 可以通過對齊方式和設定寬高因子并結合父 Widget 寬高來限制子 Widget;采用寬高因子使用更加靈活;

      與其他元件相同,通用于子 Widget 的對齊方向;

2. widthFactor

      寬度因子,若不為 null 則通過父 Widget 寬度占比來限制子 Widget 寬度;若為 null 按照父 Widget 寬度填充;

3. heightFactor

      高度因子,與 widthFactor 使用相同;

return Container(color: Colors.blueAccent.withOpacity(0.4), width: 100, height: 100,
    child: FractionallySizedBox(alignment: Alignment.center, widthFactor: 0.5, heightFactor: 0.5,
        child: Container(width: 50, height: 80, color: Colors.orange.withOpacity(0.6))));
return Container(color: Colors.blueAccent.withOpacity(0.4), width: 100, height: 100,
    child: FractionallySizedBox(alignment: Alignment.center, widthFactor: 0.5, heightFactor: null,
        child: Container(width: 200, height: 200, color: Colors.orange.withOpacity(0.6))));
return Container(color: Colors.blueAccent.withOpacity(0.4), width: 100, height: 100,
    child: FractionallySizedBox(alignment: Alignment.center, widthFactor: 1.5, heightFactor: 0.6,
        child: Container(color: Colors.orange.withOpacity(0.6))));
return Container(color: Colors.blueAccent.withOpacity(0.4), width: 100, height: 100,
    child: FractionallySizedBox(alignment: AlignmentDirectional(-0.15, -0.15), widthFactor: 0.5, heightFactor: 0.5,
        child: Container(color: Colors.orange.withOpacity(0.6))));           
Flutter 67: 圖解基本限制 Box (二)

FittedBox

class FittedBox extends SingleChildRenderObjectWidget {
  const FittedBox({
    Key key,
    this.fit = BoxFit.contain,          // 填充方式
    this.alignment = Alignment.center,  // 對齊方式
    Widget child,
  })
}           

      分析源碼可知,FittedBox 主要通過 fit 填充方式和 alignment 對齊方式對子 Widget 進行限制;且 fit / alignment 不可為空,對于圖檔的裁剪很有效;

      FittedBox 主要是通過 BoxFit 填充方式與 alignment 對齊方式共同限制子 Widget;

  1. BoxFit.fill 通過子 Widget 拉伸或壓縮填充滿父 Widget;
  2. BoxFit.contain 通過子 Widget 比例拉伸或壓縮,直到寬或高一邊填充父 Widget;
  3. BoxFit.cover 以子 Widget 寬或高填充父 Widget,剩餘一邊若超過父 Widget 對應邊則裁切;
  4. BoxFit.fitWidth 通過子 Widget 以寬為基準填充父 Widget,若高度超出會被裁切,子 Widget 不拉伸或壓縮;
  5. BoxFit.fitHeight 通過子 Widget 以高為基準填充父 Widget,若寬度超出會被裁切,子 Widget 不拉伸或壓縮;
  6. BoxFit.none 子 Widget 不拉伸或壓縮,若超出父 Widget 則被裁切;
  7. BoxFit.scaleDown 若子 Widget 可以完全放在父 Widget 中則與 BoxFit.none 效果一緻;若子 Widget 不能完全放在父 Widget 中則與 BoxFit.contain 效果一緻;
return Container(width: 100, height: 100, color: Colors.blueAccent.withOpacity(0.4),
    child: FittedBox(fit: BoxFit.cover, alignment: Alignment.topCenter, child: Image.asset("images/icon_hzw02.jpg")));
return Container(width: 100, height: 100, color: Colors.blueAccent.withOpacity(0.4),
    child: FittedBox(fit: BoxFit.fill, alignment: Alignment.topCenter, child: Image.asset("images/icon_hzw02.jpg")));
return Container(width: 100, height: 100, color: Colors.blueAccent.withOpacity(0.4),
    child: FittedBox(fit: BoxFit.fitHeight, alignment: Alignment.topCenter, child: Image.asset("images/icon_hzw02.jpg")));
return Container(width: 100, height: 100, color: Colors.blueAccent.withOpacity(0.4),
    child: FittedBox(fit: BoxFit.none, alignment: Alignment.center, child: Image.asset("images/icon_hzw02.jpg")));           
Flutter 67: 圖解基本限制 Box (二)

      Flutter 提供了多種限制 Box 方式,基本都是繼承自 SingleChildRenderObjectWidget,每種 Box 有各自特點,合理利用可以大大提高開發效率;小菜對 Box 的學習還不完整,有錯誤的地方請多多指導!

來源: 阿策小和尚

繼續閱讀