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

背景
在进行 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。
官网有如下说明:
Using an Expanded widget makes a child of a Row, Column, 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 仓库
Flutter 即学即用系列博客——07 RenderFlex overflowed 引发的思考的更多相关文章
- Flutter 即学即用系列博客——09 EventChannel 实现原生与 Flutter 通信(一)
前言 紧接着上一篇,这一篇我们讲一下原生怎么给 Flutter 发信号,即原生-> Flutter 还是通过 Flutter 官网的 Example 来讲解. 案例 接着上一次,这一次我们让原生 ...
- Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信
背景 前面我们讲了很多 Flutter 相关的知识点,但是我们并没有介绍怎样实现 Flutter 与原生的通信. 比如我在 Flutter UI 上面点击了一个按钮,我希望原生做一些处理,那么原生怎么 ...
- Flutter 即学即用系列博客总结篇
前言 迟到的总结篇,其实大家看我之前发的系列博客最后一篇,发文时间是 3 月 29 日.距离现在快两个月了. 主要是因为有很多事情在忙,所以这篇就耽搁了. 今天终于可以跟大家会面了. 系列博客背景 F ...
- Flutter 即学即用系列博客——05 StatelessWidget vs StatefulWidget
前言 上一篇我们对 Flutter UI 有了一个基本的了解. 这一篇我们通过自定义 Widget 来了解下如何写一个 Widget? 然而 Widget 有两个,StatelessWidget 和 ...
- Flutter 即学即用系列博客——04 Flutter UI 初窥
前面三篇可以算是一个小小的里程碑. 主要是介绍了 Flutter 环境的搭建.如何创建 Flutter 项目以及如何在旧有 Android 项目引入 Flutter. 这一篇我们来学习下 Flutte ...
- Flutter 即学即用系列博客——09 MethodChannel 实现原生与 Flutter 通信(二)
前言 上一篇我们讲解了如何通过 EventChannel 实现 Android -> Flutter 的通信. 并且也看到了 Flutter 内部 EventChannel 源码也是对 Meth ...
- Flutter 即学即用系列博客——06 超实用 Widget 集锦
本篇文章我们来讲讲一些比较常用的 Widget. 大家验证的时候使用下面的代码替换 main.dart 代码,然后在 //TODO 语句返回下面常用 Widget 示例的代码. import 'pac ...
- Flutter 即学即用系列博客——03 在旧有项目引入 Flutter
前言 其实如果打算在实际项目中引入 Flutter,完全将旧有项目改造成纯 Flutter 项目的可能性比较小,更多的是在旧有项目引入 Flutter. 因此本篇我们就说一说如何在旧有项目引入 Flu ...
- Flutter 即学即用系列博客——10 混淆
前言 之前的博客我们都是在 debug 的模式下进行开发的. 实际发布到市场或者给到用户的都是 release 包. 而对于 Android 来说,release 包一个重要的步骤就是混淆. Andr ...
随机推荐
- 关于input的一些问题解决方法分享
前言 input是我们接受来自用户的数据常用标签,在前端开发中,相信每个人都会用到这个标签,所以在开发过程中也时候也会遇到一些问题,本文的内容是我在跟input相爱相杀过程中产生的,在此记录分享一下. ...
- Centos下安装Python的问题汇总
Python下载地址(https://www.python.org/ftp/python/) 一.工具安装 1.Python的安装 tar vxf Python-2.7.13.tgz cd Pytho ...
- sql优化总结
在项目前期目标是确保功能能够正常运行,但是随着时间的推移,数据的增加,逻辑的复杂,导致数据查询会越来越慢,这个时候我们首先想到的应该就是尽量优化sql. sql优化常见注意点: 1.对查询进行优化,应 ...
- Linux时间子系统之(三):用户空间接口函数
专题文档汇总目录 Notes:用户空间时间相关接口函数: 类型 API 精度 说明 时间 time stime time_t 精度为秒级 逐渐要被淘汰.需要定义__ARCH_WANT_SYS_TIME ...
- Linux时间子系统之二:表示时间的单位和结构
人们习惯用于表示时间的方法是:年.月.日.时.分.秒.毫秒.星期等等,但是在内核中,为了软件逻辑和代码的方便性,它使用了一些不同的时间表示方法,并为这些表示方法定义了相应的变量和数据结构,本节的内容就 ...
- Jmeter4.0分布式测试时启动Jmeter.server时报错
最近又开始研究Jmeter,将新版本4.0下载下来体验,准备远程分布式测试,又出现一些问题,废话不多说,直入主题把! Windows 系统启动Jmeter 4.0的JmeterServer.ba ...
- nagios监控mysql主机,nginx,磁盘IO,网卡流量
http://blog.chinaunix.net/uid-28685162-id-3506260.html nagios安装完成,打开/usr/local/nagios/etc/nagios.cfg ...
- Day1----Python学习之路笔记(1)
学习路线 Day1 Day2 Day3 Day4 Day5 ...待续 一.了解开发语言 1.高级语言:Python,Java,C++,C#,PHP,JS,Go,Ruby,SQL,Swift,Perl ...
- 关于top命令的使用
在服务器运维过程中,我们有时需要知道当前状态下的系统运行性能,该如何获取呢?今天,咱们聊一下关于top这个小命令的一些知识. top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资 ...
- 【转】一则使用WinDbg工具调试iis进程调查内存占用过高的案例
最近遇到一个奇葩内存问题,跟了三四天,把Windbg玩熟了,所以打算分享下. 症状简介 我们团队的DEV开发环境只有一台4核16G的win2012r2.这台服务器上装了SqlServer.TFS(项目 ...