当前位置: 萬仟网 > IT编程>移动>Android > Flutter 即学即用系列博客——07 RenderFlex overflowed 引发的思考

Flutter 即学即用系列博客——07 RenderFlex overflowed 引发的思考

31  人参与 | 时间:2019-03-11 | 我要评论

背景

在进行 flutter ui 开发的时候,控制台报出了下面错误:

flutter: ══╡ exception caught by rendering library >╞═════════════════════════════════════════════════════════
flutter: the following message was thrown during layout:
flutter: a renderflex overflowed by 826 pixels on the right.

界面的体现就是黄色区域。

这里的代码是在上一篇的基础上返回下面的 widget:

return row(
      children: <widget>[
        image.network(
            'https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imagemogr2/auto-orient/strip%7cimageview2/2/w/1240')
      ],
    );

模拟器效果如下:

思考

其实一般遇到这种情况,都应该考虑一下是否这样布局合理。

上面这个我们只是举个例子,因为一般如果只有一张图片,是不需要给他套一层 row 的。

因为情况比较多,这里假设有时候真的就需要这么处理,怎么办?

解决方法

如果你某个 widget 出现了上面的问题,而且真的不是布局问题,而是真的就是有可能出现这种情况,但是你不希望 debug 模式显示这个错误,那么可以给他套一层 expanded。

官网有如下说明:

a widget that expands a child of a rowcolumn, or flex.

using an expanded widget makes a child of a rowcolumn, or flex expand to fill the available space in the main axis (e.g., horizontally for a row or vertically for a column). if multiple children are expanded, the available space is divided among them according to the flex factor.

所以对于 row、column 以及 flex 都可以用 expanded 来解决子组件报上面错误问题。

所以这里可以修改为

return row(
      children: <widget>[
        expanded(
          child: image.network(
              'https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imagemogr2/auto-orient/strip%7cimageview2/2/w/1240'),,
        )
      ],
    );

效果如下:

expanded 妙用

expanded 除了可以解决上面的问题之外,还有一个妙用就是比例布局。

什么意思呢?

我们写下代码,然后给下效果图你就懂了。

return column(
      children: <widget>[
        expanded(
          flex: 1,
          child: container(
            color: colors.red,
          ),
        ),
        expanded(
          flex: 1,
          child: container(
            color: colors.blue,
          ),
        ),
        expanded(
          flex: 1,
          child: container(
            color: colors.grey,
          ),
        ),
      ],
    );

效果图如下:

可以看出 expanded 的 flex 属性会按比例布局。

sample

我们来实现一个简单的 ui。

如下图,可以看到是一个网络错误时,点击重试的页面。

假设你之前习惯了 sketch 边距开发,你看到这个页面,就直接根据边距进行开发,写出了下面的代码。

实现方式一:

import 'package:flutter/material.dart';

void main() => runapp(myapp());

class myapp extends statelesswidget {
  @override
  widget build(buildcontext context) {

    return materialapp(
      home: scaffold(
        backgroundcolor: color(0xfff0f1f0),
        body: center(
          child: _buildwidget(),
        ),
      ),
    );
  }

  widget _buildwidget() {
    return container(
      child: column(
        children: <widget>[
          padding(
            padding: const edgeinsets.only(left: 97.0, right: 97.0, top: 125),
            child: image.asset('assets/images/refresh.png', width: 49, height: 44,),
          ),
          sizedbox(
            height: 42.0,
          ),
          flatbutton(
              padding: const edgeinsets.symmetric(horizontal: 50.0),
              //注意这里 alpha 最大值是 255, sketch 上面最大值是 100
              color: color.fromargb(255, 13, 46, 172),
              //这里 onpressed 不能为 null,如果写 null 会怎样,大家可以试下~
              onpressed: (){},
              child: text(
                //演示而已,实际开发需要多语言
                '刷新',
                style: textstyle(
                    color: colors.white,
                    fontsize: 12,
                    fontweight: fontweight.w600
                ),
              )
          )
        ],
      ),
    );
  }

}

效果如下:

你会发现这种实现方式的适配性会很差,而且可能出现上面的问题。

因此我们看下使用 expanded 如何实现。

观察一下,我们发现界面大概可以分成 3 块。

每一块占的比例差不多,因此可以如下实现。

实现方式二:

import 'package:flutter/material.dart';

void main() => runapp(myapp());

class myapp extends statelesswidget {
  @override
  widget build(buildcontext context) {

    return materialapp(
      home: scaffold(
        backgroundcolor: color(0xfff0f1f0),
        body: center(
          child: _buildwidget(),
        ),
      ),
    );
  }

  widget _buildwidget() {
    return container(
      child: column(
        children: <widget>[
          expanded(
            flex: 1,
            child: container(),
          ),
          image.asset('assets/images/refresh.png', width: 49, height: 44,),
          sizedbox(
            height: 42.0,
          ),
          flatbutton(
              padding: const edgeinsets.symmetric(horizontal: 50.0),
              //注意这里 alpha 最大值是 255, sketch 上面最大值是 100
              color: color.fromargb(255, 13, 46, 172),
              //这里 onpressed 不能为 null,如果写 null 会怎样,大家可以试下~
              onpressed: (){},
              child: text(
                //演示而已,实际开发需要多语言
                '刷新',
                style: textstyle(
                    color: colors.white,
                    fontsize: 12,
                    fontweight: fontweight.w600
                ),
              )
          ),
          expanded(
            flex: 1,
            child: container(),
          ),
        ],
      ),
    );
  }

}

效果如下:

其实,看到上面用到的 column,我们可以直接利用上次说到的一个属性,就可以很巧妙的实现适配。

实现方式三:

import 'package:flutter/material.dart';

void main() => runapp(myapp());

class myapp extends statelesswidget {
  @override
  widget build(buildcontext context) {
    return materialapp(
      home: scaffold(
        backgroundcolor: color(0xfff0f1f0),
        body: center(
          child: _buildwidget(),
        ),
      ),
    );
  }

  widget _buildwidget() {
    return container(
      child: column(
        mainaxisalignment: mainaxisalignment.center,
        children: <widget>[
          image.asset(
            'assets/images/refresh.png',
            width: 49,
            height: 44,
          ),
          sizedbox(
            height: 42.0,
          ),
          flatbutton(
              padding: const edgeinsets.symmetric(horizontal: 50.0),
              //注意这里 alpha 最大值是 255, sketch 上面最大值是 100
              color: color.fromargb(255, 13, 46, 172),
              //这里 onpressed 不能为 null,如果写 null 会怎样,大家可以试下~
              onpressed: () {},
              child: text(
                //演示而已,实际开发需要多语言
                '刷新',
                style: textstyle(
                    color: colors.white,
                    fontsize: 12,
                    fontweight: fontweight.w600),
              )),
        ],
      ),
    );
  }
}

效果如下:

其中实现方式一只是说明,实际开发不推荐。

实现方式二和实现方式三都可以,推荐方式三。

相关代码及 sketch 图都放到了 github 仓库

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

◎已有 0 人评论

Copyright © 2019  萬仟网 保留所有权利. 粤ICP备17035492号-1
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com