Flutter FittedBox

🔥 英文单词FittedBox 🔥

Fitted 通过有道翻译如下 :

Box 通过有道翻译如下 :

对 FittedBox 的理解

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

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

🔥 为什么使用 FittedBox 🔥

使用 FittedBox 的原因

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

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

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

Text 文本溢出

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

Image 加载网络图片溢出

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

🔥 FittedBox 属性 🔥

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

BoxFit.none

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

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

BoxFit.contain

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

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

BoxFit.fitWidth / fitHeight

需要设置 FittedBox 的大小,不然设置 BoxFit.fitWidth 和 BoxFit.fitHeight 无效。
当没有设置 FittedBox 大小时,文本始终显示在屏幕的范围内,填充屏幕宽度。

Dart 复制代码
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),
              ),
            ],
          ),
        ),
      )
Dart 复制代码
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),
              ),
            ],
          ),
        ),
      )


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

Dart 复制代码
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),
              ),
            ],
          ),
        ),
      )
Dart 复制代码
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),
              ),
            ],
          ),
        ),
      )

Boxfit.scaleDown

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

Dart 复制代码
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),
              ),
            ],
          ),
        ),
      )
Dart 复制代码
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),
              ),
            ],
          ),
        ),
      )

Boxfit.fill

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

Dart 复制代码
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),
              ),
            ],
          ),
        ),
      )
Dart 复制代码
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),
              ),
            ],
          ),
        ),
      )

Boxfit.cover

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

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

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

Dart 复制代码
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),
              ),
            ],
          ),
        ),
      )
Dart 复制代码
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),
              ),
            ],
          ),
        ),
      )

Clip.none

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

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

剪切前

Clip.hardEdge

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

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

剪切后

🔥 裁剪超范围区域 🔥

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

🔥 打印布局时的约束信息 🔥

Dart 复制代码
class LayoutLogPrint<T> 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;
    });
  }
}
Dart 复制代码
Column(
        children: [
          wRow(' 内容是否发生溢出/ '),
          FittedBox(child: wRow(' 内容是否发生溢出/ ')),
        ]
            .map((e) => Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20),
                  child: e,
                ))
            .toList(),
      )
Dart 复制代码
  // 直接使用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);
  }
Dart 复制代码
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)

🔥 使用FittedBox也发生溢出 🔥

Dart 复制代码
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,
          ),
        );
      },
    );
  }
}
Dart 复制代码
Column(
        children: [
          wRow(' 内容是否发生溢出 '),
          SingleLineFittedBox(child: wRow(' 内容是否发生溢出 ')),
          wRow(' 少内容 '),
          FittedBox(
            child: wRow(' 内容太挤内容太挤内容太挤内容太挤内容太挤内容太挤内容太挤内容太挤内容太挤内容太挤 '),
          )
        ]
            .map((e) => Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20),
                  child: e,
                ))
            .toList(),
      )
Dart 复制代码
// 直接使用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;
  }

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

相关推荐
problc3 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
lqj_本人11 小时前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人15 小时前
Flutter&鸿蒙next 状态管理框架对比分析
flutter·华为·harmonyos
起司锅仔19 小时前
Flutter启动流程(2)
flutter
hello world smile1 天前
最全的Flutter中pubspec.yaml及其yaml 语法的使用说明
android·前端·javascript·flutter·dart·yaml·pubspec.yaml
lqj_本人1 天前
Flutter 的 Widget 概述与常用 Widgets 与鸿蒙 Next 的对比
flutter·harmonyos
iFlyCai1 天前
极简实现酷炫动效:Flutter隐式动画指南第二篇之一些酷炫的隐式动画效果
flutter
lqj_本人1 天前
Flutter&鸿蒙next 中使用 MobX 进行状态管理
flutter·华为·harmonyos
lqj_本人1 天前
Flutter&鸿蒙next 中的 setState 使用场景与最佳实践
flutter·华为·harmonyos
hello world smile1 天前
Flutter常用命令整理
android·flutter·移动开发·android studio·安卓