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),则就可以处理数字总长度超出屏幕宽度的情况。

相关推荐
江上清风山间明月1 天前
Flutter开发的应用页面非常多时如何高效管理路由
android·flutter·路由·页面管理·routes·ongenerateroute
Zsnoin能1 天前
flutter国际化、主题配置、视频播放器UI、扫码功能、水波纹问题
flutter
早起的年轻人1 天前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
HappyAcmen1 天前
关于Flutter前端面试题及其答案解析
前端·flutter
coooliang2 天前
Flutter 中的单例模式
javascript·flutter·单例模式
coooliang2 天前
Flutter项目中设置安卓启动页
android·flutter
JIngles1232 天前
flutter将utf-8编码的字节序列转换为中英文字符串
java·javascript·flutter
B.-2 天前
在 Flutter 中实现文件读写
开发语言·学习·flutter·android studio·xcode
freflying11192 天前
使用jenkins构建Android+Flutter项目依赖自动升级带来兼容性问题及Jenkins构建速度慢问题解决
android·flutter·jenkins
机器瓦力2 天前
Flutter应用开发:对象存储管理图片
flutter