背景

在进行 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 仓库

Flutter 即学即用系列博客——07 RenderFlex overflowed 引发的思考的更多相关文章

  1. Flutter 即学即用系列博客——09 EventChannel 实现原生与 Flutter 通信(一)

    前言 紧接着上一篇,这一篇我们讲一下原生怎么给 Flutter 发信号,即原生-> Flutter 还是通过 Flutter 官网的 Example 来讲解. 案例 接着上一次,这一次我们让原生 ...

  2. Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信

    背景 前面我们讲了很多 Flutter 相关的知识点,但是我们并没有介绍怎样实现 Flutter 与原生的通信. 比如我在 Flutter UI 上面点击了一个按钮,我希望原生做一些处理,那么原生怎么 ...

  3. Flutter 即学即用系列博客总结篇

    前言 迟到的总结篇,其实大家看我之前发的系列博客最后一篇,发文时间是 3 月 29 日.距离现在快两个月了. 主要是因为有很多事情在忙,所以这篇就耽搁了. 今天终于可以跟大家会面了. 系列博客背景 F ...

  4. Flutter 即学即用系列博客——05 StatelessWidget vs StatefulWidget

    前言 上一篇我们对 Flutter UI 有了一个基本的了解. 这一篇我们通过自定义 Widget 来了解下如何写一个 Widget? 然而 Widget 有两个,StatelessWidget 和 ...

  5. Flutter 即学即用系列博客——04 Flutter UI 初窥

    前面三篇可以算是一个小小的里程碑. 主要是介绍了 Flutter 环境的搭建.如何创建 Flutter 项目以及如何在旧有 Android 项目引入 Flutter. 这一篇我们来学习下 Flutte ...

  6. Flutter 即学即用系列博客——09 MethodChannel 实现原生与 Flutter 通信(二)

    前言 上一篇我们讲解了如何通过 EventChannel 实现 Android -> Flutter 的通信. 并且也看到了 Flutter 内部 EventChannel 源码也是对 Meth ...

  7. Flutter 即学即用系列博客——06 超实用 Widget 集锦

    本篇文章我们来讲讲一些比较常用的 Widget. 大家验证的时候使用下面的代码替换 main.dart 代码,然后在 //TODO 语句返回下面常用 Widget 示例的代码. import 'pac ...

  8. Flutter 即学即用系列博客——03 在旧有项目引入 Flutter

    前言 其实如果打算在实际项目中引入 Flutter,完全将旧有项目改造成纯 Flutter 项目的可能性比较小,更多的是在旧有项目引入 Flutter. 因此本篇我们就说一说如何在旧有项目引入 Flu ...

  9. Flutter 即学即用系列博客——10 混淆

    前言 之前的博客我们都是在 debug 的模式下进行开发的. 实际发布到市场或者给到用户的都是 release 包. 而对于 Android 来说,release 包一个重要的步骤就是混淆. Andr ...

随机推荐

  1. Intent传值的学习

    今天学习了Intent传值的过程,有点安卓编程经验的都知道,Intent可以实现页面的跳转,可以从一个activity跳转到另一个activity,这个名义上说是界面跳转,其实这句话现在觉得说的很不严 ...

  2. vue项目如何刷新当前页面

    1.场景 在处理列表时,常常有删除一条数据或者新增数据之后需要重新刷新当前页面的需求. 2.遇到的问题 1. 用vue-router重新路由到当前页面,页面是不进行刷新的 2.采用window.rel ...

  3. Kali Linux远程连接Windows服务器

    前言: 为了在Kali上远程连接Windows系统的服务器我们需要安装两个工具,rdesktop和tsclient.另外,我们从主机服务商那里购买的Windows操作系统的服务器都是默认开启了远程连接 ...

  4. Ambiguous mapping found

    If you have a single default method (without explicit path mapping), then all requests without a mor ...

  5. Python爬虫-pyspider框架的使用

      pyspider 是一个用python实现的功能强大的网络爬虫系统,能在浏览器界面上进行脚本的编写,功能的调度和爬取结果的实时查看,后端使用常用的数据库进行爬取结果的存储,还能定时设置任务与任务优 ...

  6. Java 中的纤程库 – Quasar

    来源:鸟窝, colobu.com/2016/07/14/Java-Fiber-Quasar/ 如有好文章投稿,请点击 → 这里了解详情 最近遇到的一个问题大概是微服务架构中经常会遇到的一个问题: 服 ...

  7. .net core在网关中统一配置Swagger

    最近在做微服务的时候,由于我们是采用前后端分离来开发的,提供给前端的直接是Swagger,如果Swagger分布在各个API中,前端查看Swagger的时候非常不便,因此,我们试着将Swagger集中 ...

  8. BZOJ_1098_[POI2007]办公楼biu_链表优化BFS

    BZOJ_1098_[POI2007]办公楼biu_链表优化BFS Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的 电话号 ...

  9. BZOJ_5296_[Cqoi2018]破解D-H协议_BSGS

    BZOJ_5296_[Cqoi2018]破解D-H协议_BSGS Description Diffie-Hellman密钥交换协议是一种简单有效的密钥交换方法.它可以让通讯双方在没有事先约定密钥(密码 ...

  10. ionic3 懒加载在微信上缓存的问题

    1.懒加载是什么? 在ionic2中所有的组件.模块.服务.管道等都堆积在app.module.ts模块中,在页面初始化的时候会一次性加载所有的资源,导致资源过大,页面渲染缓慢,也导致app.modu ...