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 ...
随机推荐
- 读《图解HTTP》有感-(确保WEB安全的HTTPS)
写在前面 该章节分析当前使用的HTTP协议中存在的安全性问题,以及采用HTTPS协议来规避这些可能存在的缺陷 正文 1.HTTP的缺点 1.1.由于HTTP不具备加密功能,所以在通信链路上,报文是以明 ...
- Net Core动态加载webservice/WCF
1.动态加载的目的 前端时间和顺丰对接了个项目(PS:顺丰的开发对外能力真的是掉粉),用的webservice 测试时用的无固定IP访问,正式版需要固定IP访问,我的理解是web服务都是全网络可以访问 ...
- PAT1082:Read Number in Chinese
1082. Read Number in Chinese (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yu ...
- Deep Learning Enables You to Hide Screen when Your Boss is Approaching
https://github.com/Hironsan/BossSensor/ 背景介绍 学生时代,老师站在窗外的阴影挥之不去.大家在玩手机,看漫画,看小说的时候,总是会找同桌帮忙看着班主任有没有来. ...
- toFixed()一不小心踩了一个坑
toFixed,多么简单的一个函数,昨天突发奇想做两道算法题练练手.结果,踩到了一个从未遇到的坑! \n 简单来讲是要对输入的很多组数据,自己写一个函数做个处理,把每次函数处理的结果要相加求和.最后输 ...
- Selenium库,Python精品教程!
什么是Selenium selenium基本使用 用python写爬虫的时候,主要用的是selenium的Webdriver,我们可以通过下面的方式先看看Selenium.Webdriver支持哪些浏 ...
- 阿里巴巴的开源项目Druid(关于数据库连接)
1 配置 和dbcp类似,druid的常用配置项如下 配置 缺省值 说明 name 配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来.如果没有配置,将会生成一个名字,格 ...
- nodejs-5.1 ejs模板引擎
ejs官方文档:https://ejs.bootcss.com/ 1.什么是 EJS? "E" 代表 "effective",即[高效]. EJS 是一套简单的 ...
- 【爆料】-《维多利亚大学毕业证书》Victoria一模一样原件
☞维多利亚大学毕业证书[微/Q:865121257◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归& ...
- Java报错信息 java.lang.SecurityException: Prohibited package name: java.xxx
package java.yun.System; public class SystemOut { public static void main(String[] args) { System.ou ...