Flutter FittedBox

英文单词FittedBox 

Fitted 通过有道翻译如下 : 

Flutter FittedBox_第1张图片

Flutter FittedBox_第2张图片

Box 通过有道翻译如下 : 

 Flutter FittedBox_第3张图片

 对 FittedBox 的理解

我们可以将 FittedBox 理解为合适的盒子,将其它布局放到FittedBox这样一个盒子中,从而实现 盒子里面的子布局更好的放置。

 参考 Flutter实战 空间适配(FittedBox)

为什么使用 FittedBox

使用 FittedBox 的原因

        在开发的过程中经常会遇到子widget大小超过父widget大小的现象。子widget应该遵循父widget的约束,如果子widget的原始大小超过了父原始视图的大小,就需要进行相应的处理(比如:缩小、裁剪等)。

        如果父 widget 宽度固定高度不固定,则默认情况下 Text 会在文本到达父组件宽度的时候换行。

        如果我们想让 Text 文本在超过父组件的宽度时不要换行而是字体缩小,这时候就需要用到 FittedBox 组件

        

Text 文本溢出  

Row(
   children: [
    Text(
       '文本内容过长就超出屏幕宽度/' * 30,
        style: TextStyle(color: Colors.blue, fontSize: 60.sp),
        ),
   ],
)

Flutter FittedBox_第4张图片

Image 加载网络图片溢出 

Row(
  children: [
    Image.network(
     'https://www.2008php.com/2011_Website_appreciate/2011-03-28/20110328134546.jpg'),
        ],
)

Flutter FittedBox_第5张图片

  FittedBox 属性

final BoxFit  fit // 适配方式
final AlignmentGeometry alignment ; // 对齐方式
final Clip clipBehavior ; // 是否剪裁

BoxFit.none

显示屏幕范围宽度的内容, 超过屏幕范围的内容不显示

FittedBox(
            fit: BoxFit.none,
        child: Row(
          children: [
            Text(
              '文本内容过长就超出屏幕宽度/' * 7,
              style: TextStyle(color: Colors.blue, fontSize: 60.sp),
            ),
          ],
        ),
      )

Flutter FittedBox_第6张图片

 BoxFit.contain

文本所有内容都显示到屏幕范围内,按字体大小进行缩小

FittedBox(
            fit: BoxFit.contain,
        child: Row(
          children: [
            Text(
              '文本内容过长就超出屏幕宽度/' * 7,
              style: TextStyle(color: Colors.blue, fontSize: 60.sp),
            ),
          ],
        ),
)

Flutter FittedBox_第7张图片

 BoxFit.fitWidth / fitHeight

需要设置 FittedBox 的大小,不然设置 BoxFit.fitWidth BoxFit.fitHeight 无效。

 当没有设置 FittedBox 大小时,文本始终显示在屏幕的范围内,填充屏幕宽度

SizedBox(
        /*height: 20.w,
        width: double.infinity,*/
        child: FittedBox(
          fit: BoxFit.fitHeight,
          child: Row(
            children: [
              Text(
                '文本内容过长就超出屏幕宽度/' * 3,
                style: TextStyle(color: Colors.blue, fontSize: 60.sp),
              ),
            ],
          ),
        ),
      )

Flutter FittedBox_第8张图片

SizedBox(
        /*height: 20.w,
        width: double.infinity,*/
        child: FittedBox(
          fit: BoxFit.fitWidth,
          child: Row(
            children: [
              Text(
                '文本内容过长就超出屏幕宽度/' * 3,
                style: TextStyle(color: Colors.blue, fontSize: 60.sp),
              ),
            ],
          ),
        ),
      )

Flutter FittedBox_第9张图片

        当设置 FittedBox 大小时,文本始终显示在屏幕的范围内;如果是 BoxFit.fitWidth 填充屏幕宽度的形式展示文本,如果是 BoxFit.fitHeight 填充屏幕高度的形式展示文本。

SizedBox(
        height: 50.w,
        width: double.infinity,
        child: FittedBox(
          fit: BoxFit.fitHeight,
          child: Row(
            children: [
              Text(
                '文本内容过长就超出屏幕宽度/' * 3,
                style: TextStyle(color: Colors.blue, fontSize: 60.sp),
              ),
            ],
          ),
        ),
      )

Flutter FittedBox_第10张图片

SizedBox(
        height: 50.w,
        width: double.infinity,
        child: FittedBox(
          fit: BoxFit.fitWidth,
          child: Row(
            children: [
              Text(
                '文本内容过长就超出屏幕宽度/' * 3,
                style: TextStyle(color: Colors.blue, fontSize: 60.sp),
              ),
            ],
          ),
        ),
      )

Flutter FittedBox_第11张图片

Boxfit.scaleDown

保证不超过 父 Widget的大小。如果字体原始的高度比父容器的高度小,那么就按照父容器的高度进行缩小;如果原始字体宽度比父容器的宽度小,就按照父容器的宽度进行缩小。

SizedBox(
        height: 10.w,
        width: double.infinity,
        child: FittedBox(
          fit: BoxFit.scaleDown,
          child: Row(
            children: [
              Text(
                '文本内容过长就超出屏幕宽度/' * 3,
                style: TextStyle(color: Colors.blue, fontSize: 60.sp),
              ),
            ],
          ),
        ),
      )

Flutter FittedBox_第12张图片

SizedBox(
        height: 40.w,
        width: double.infinity,
        child: FittedBox(
          fit: BoxFit.scaleDown,
          child: Row(
            children: [
              Text(
                '文本内容过长就超出屏幕宽度/' * 3,
                style: TextStyle(color: Colors.blue, fontSize: 60.sp),
              ),
            ],
          ),
        ),
      )

Flutter FittedBox_第13张图片

 Boxfit.fill

保证不超过 父 Widget的大小。如果字体原始的高度比父容器的高度小,那么久拉伸字体高度到容器高度,相反就压缩字体高度到父容器高度。

SizedBox(
        height: 140.w,
        width: double.infinity,
        child: FittedBox(
          fit: BoxFit.fill,
          child: Row(
            children: [
              Text(
                '文本内容过长就超出屏幕宽度/' * 3,
                style: TextStyle(color: Colors.blue, fontSize: 60.sp),
              ),
            ],
          ),
        ),
      )

 Flutter FittedBox_第14张图片

SizedBox(
        height: 14.w,
        width: double.infinity,
        child: FittedBox(
          fit: BoxFit.fill,
          child: Row(
            children: [
              Text(
                '文本内容过长就超出屏幕宽度/' * 3,
                style: TextStyle(color: Colors.blue, fontSize: 60.sp),
              ),
            ],
          ),
        ),
      )

 Flutter FittedBox_第15张图片

 Boxfit.cover

内容按照原始尺寸填充父容器的宽或者高,但可能会超过父容器的范围。

如果字体原始高度小于 父容器高度,这时候就填充高度 ,可能会出现超过父容器范围的情况。

如果字体原始高度不小于 父容器高度,这时候就填充宽度,不会出现超过父容器的情况。

SizedBox(
        height: 80.w,
        width: double.infinity,
        child: FittedBox(
          fit: BoxFit.cover,
          child: Row(
            children: [
              Text(
                '文本内容过长就超出屏幕宽度/' * 3,
                style: TextStyle(color: Colors.blue, fontSize: 60.sp),
              ),
            ],
          ),
        ),
      )

Flutter FittedBox_第16张图片

SizedBox(
        height: 2.w,
        width: double.infinity,
        child: FittedBox(
          fit: BoxFit.cover,
          child: Row(
            children: [
              Text(
                '文本内容过长就超出屏幕宽度/' * 3,
                style: TextStyle(color: Colors.blue, fontSize: 60.sp),
              ),
            ],
          ),
        ),
      )

 Flutter FittedBox_第17张图片

Clip.none

如果子Widget的高度超过父视图的高度,不做裁剪,那么高度就显示成子视图的高度

Container(
            width: 160,
            height: 150,
            color: Colors.red,
            child: FittedBox(
              fit: BoxFit.fitWidth,
              clipBehavior: Clip.none,
              child: Container(width: 160, height: 200, color: Colors.blue),
            ),
          )

剪切前

Flutter FittedBox_第18张图片

 Clip.hardEdge

如果子Widget的高度超过父视图的高度,就进行裁剪,高度就显示成夫视图的高度。

Container(
            width: 160,
            height: 150,
            color: Colors.red,
            child: FittedBox(
              fit: BoxFit.fitWidth,
              clipBehavior: Clip.hardEdge,
              child: Container(width: 160, height: 200, color: Colors.blue),
            ),
          )

剪切后 

Flutter FittedBox_第19张图片

裁剪超范围区域

ClipRect(
        // 将超出子组件布局范围的绘制内容剪裁掉
        child: Container(
          width: 50,
          height: 50,
          color: Colors.red,
          child: FittedBox(
            fit: BoxFit.none,
            child: Container(width: 60, height: 70, color: Colors.blue),
          ),
        ),
      )

Flutter FittedBox_第20张图片

  打印布局时的约束信息

class LayoutLogPrint extends StatelessWidget {
  const LayoutLogPrint({
    Key? key,
    this.tag,
    required this.child,
  }) : super(key: key);

  final Widget child;
  final T? tag; //指定日志tag

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (_, constraints) {
      // assert在编译release版本时会被去除
      assert(() {
        if (kDebugMode) {
          print('${tag ?? key ?? child}: $constraints');
        }
        return true;
      }());
      return child;
    });
  }
}
Column(
        children: [
          wRow(' 内容是否发生溢出/ '),
          FittedBox(child: wRow(' 内容是否发生溢出/ ')),
        ]
            .map((e) => Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20),
                  child: e,
                ))
            .toList(),
      )
  // 直接使用Row
  Widget wRow(String text) {
    Widget child = Text(
      text,
      style: const TextStyle(color: Colors.black, fontSize: 20.0),
    );
    child = Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [child, child, child],
    );
    return LayoutLogPrint(child: child);
  }

Flutter FittedBox_第21张图片

I/flutter (13152): Row(direction: horizontal, mainAxisAlignment: spaceEvenly, crossAxisAlignment: center): BoxConstraints(0.0<=w<=392.7, 0.0<=h<=Infinity)
I/flutter (13152): Row(direction: horizontal, mainAxisAlignment: spaceEvenly, crossAxisAlignment: center): BoxConstraints(unconstrained)

Flutter FittedBox_第22张图片

  使用FittedBox也发生溢出   

class SingleLineFittedBox extends StatelessWidget {
  const SingleLineFittedBox({Key? key,this.child}) : super(key: key);
  final Widget? child;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (_, constraints) {
        return FittedBox(
          child: ConstrainedBox(
            constraints: constraints.copyWith(
              //让 maxWidth 使用屏幕宽度
                maxWidth: constraints.maxWidth
            ),
            child: child,
          ),
        );
      },
    );
  }
}
Column(
        children: [
          wRow(' 内容是否发生溢出 '),
          SingleLineFittedBox(child: wRow(' 内容是否发生溢出 ')),
          wRow(' 少内容 '),
          FittedBox(
            child: wRow(' 内容太挤内容太挤内容太挤内容太挤内容太挤内容太挤内容太挤内容太挤内容太挤内容太挤 '),
          )
        ]
            .map((e) => Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20),
                  child: e,
                ))
            .toList(),
      )
// 直接使用Row
  Widget wRow(String text) {
    Widget child = Text(
      text,
      style: const TextStyle(color: Colors.black, fontSize: 16.0),
    );
    child = Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [child, child, child],
    );
    return child;
  }

Flutter FittedBox_第23张图片

SingleLineFittedBox 中将传给 Row 的 maxWidth 置为屏幕宽度后,效果和不加 SingleLineFittedBox 的效果是一样的。

 解决方案: 最小宽度(minWidth)约束指定为屏幕宽度 , 因为Row必须得遵守父组件的约束,所以 Row 的宽度至少等于屏幕宽度,所以就不会出现缩在一起的情况;同时我们将 maxWidth 指定为无限大 (double.infinity),则就可以处理数字总长度超出屏幕宽度的情况。

Flutter FittedBox_第24张图片

 

Flutter FittedBox_第25张图片

你可能感兴趣的:(Flutter,杂文,flutter)