写点什么

【Flutter 专题】67 图解基本约束 Box (二)

发布于: 1 小时前
【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 的对齐方向,可以通过 AlignmentAlignmentDirectional 进行调整所在位置;其中 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))));
复制代码



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))));
复制代码



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. LimitedBoxWidget 无限制,子 Widget 宽高小于约束最大宽高;


return Container(child: LimitedBox(maxWidth: 100, maxHeight: 100, child: Container(width: 80, height: 80, color: Colors.purple.withOpacity(0.4))));
复制代码



  1. LimitedBoxWidget 无限制,子 Widget 宽高大于约束最大宽高;


return Container(child: LimitedBox(maxWidth: 100, maxHeight: 100, child: Container(width: 160, height: 160, color: Colors.orange.withOpacity(0.4))));
复制代码



  1. LimitedBoxWidget 有限制时;无论 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))));
复制代码



FractionallySizedBox

源码分析

class FractionallySizedBox extends SingleChildRenderObjectWidget {  const FractionallySizedBox({    Key key,    this.alignment = Alignment.center,  // 对齐方式    this.widthFactor,                   // 宽度因子    this.heightFactor,                  // 高度因子    Widget child,  })}
复制代码


      分析源码可知,FractionallySizedBox 可以通过对齐方式和设置宽高因子并结合父 Widget 宽高来约束子 Widget;采用宽高因子使用更加灵活;

案例尝试

1. alignment

      与其他组件相同,通用于子 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))));
复制代码



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.noneWidget 不拉伸或压缩,若超出父 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 提供了多种约束 Box 方式,基本都是继承自 SingleChildRenderObjectWidget,每种 Box 有各自特点,合理利用可以大大提高开发效率;小菜对 Box 的学习还不完整,有错误的地方请多多指导!


来源: 阿策小和尚

发布于: 1 小时前阅读数: 2
用户头像

还未添加个人签名 2021.05.13 加入

Android / Flutter 小菜鸟~

评论

发布
暂无评论
【Flutter 专题】67 图解基本约束 Box (二)