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

本篇文章我们来讲讲一些比较常用的 Widget。
大家验证的时候使用下面的代码替换 main.dart 代码,然后在 //TODO 语句返回下面常用 Widget 示例的代码。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: _buildWidget(),
),
),
);
}
Widget _buildWidget() {
//TODO
}
}
目录

1. Text
1)基本使用
return Text('Show Regular Text');
2)设置字体样式
属性:style
设置粗体:
return Text(
'Show Bold Text',
style: TextStyle(fontWeight: FontWeight.bold),
);
设置颜色:
return Text(
'Show Bold Red Text',
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.red),
);
其他样式相信大家学习过之前的文章,知道如何查看一个 Widget 源码以及如何使用了。
3)设置最大行数及省略号
属性:maxLines、overflow
return Container(
width: 100,
child: Text(
'设置文本超过 100,这样能够看到效果,这里设置最多显示一行',
maxLines: 1, //设置最大行数
overflow: TextOverflow.ellipsis, //设置超过显示省略号
),
);
大概效果如下:

2. Image
1)本地加载图片
第一步:创建放置图片的文件夹,这里假设我们在 my_flutter 下面创建 assets/images/2.0x 和 assets/images/3.0x 文件夹用于存放本地图片。
第二步:拷贝图片 wechat.png 到上述文件夹,一般如果切图是用 sketch,则直接选择对应的 2 倍图和 3 倍图。
第三步:在 pubspec.yaml 文件确定要使用的图片资源位置。这里可以定义如下:
assets:
- assets/images/wechat.png
第四步:使用如下。
return Image.asset('assets/images/wechat.png')
可能有小伙伴会觉得,如果我有很多图片需要使用,是不是每次执行第三步和第四步的时候都要写那么长的路径。
先说下第四步,如果你都是同个目录,只是最后图片名称不一样。那么你可以自定义一个包装类做一层包装。
接着我们来说下第三步的情况。
假设你有很多图片在同一个文件夹下面,那么你是可以在 pubspec.yaml 里面使用目录定义的。但是,注意官方文档的一句话:
Note that only files located directly in the directory will be included; to add files located in subdirectories, create an entry per directory.
简单的说就是你使用的目录要到最底层,也就是这个目录下面就是图片而不是目录了。
举我们这个例子就是如果你要用目录定义及使用,上面第三步替换为
assets:
- assets/images/2.0x/
第四步替换为
return Image.asset('assets/images/2.0x/wechat.png');
可以看到这样我们如果一张图片要适配不同尺寸估计就不是很合适了。
因此对于有适配场景的,其实推荐第一种直接配置指定图片的方式。
温馨提示:
修改 pubspec.yaml 文件之后建议运行之前增加清理工作。
比如之前是执行 flutter run
修改之后建议执行 flutter packages get;flutter clean;flutter run
上面定义的位置可以直接在 pubspec.yaml 文件搜索 assets,有注释讲解的位置就是你要添加的位置了。
官网:
https://flutter.dev/docs/development/ui/assets-and-images#loading-images
2)网络加载图片
给定一个图片 url,执行下面代码即可:
return Image.network('https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240');
3)指定宽高
指定宽高是直接使用 width 和 height 属性。
比如网络加载图片指定宽高如下:
return Image.network(
'https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
width: 300,
height: 200,
);
大致效果如下:

3. Column
前面两个讲的都是单个小组件。接下来我们讲的是类似于布局的组件。(还是组件,毕竟 Flutter 一切皆 Widget)
1)基本使用
大家看到这个词,应该会直观认为这个就是对于一些布局为列的场景吧,可能有多列,然而不是哦。
点进去源码可以看到如下注释:
/// Creates a vertical array of children.
大概意思是创建一组垂直的子组件集合。
如果你是 Android 开发,可以联想到 LinearLayout 里面的 orientation 设置为 vertical 时的布局。
如下:

你也可以这样记忆,Column 是列,说明布局只有一列。所以就是上面这种了。
所以上面的 Text 效果图和 Image 效果图应该就知道是如何显示了吧?
我们这里给下示例代码,当然如果你是用带刘海屏的设备运行,可能顶部会看不到。后面我们会继续说明。
return Column(
children: <Widget>[
Image.asset('assets/images/wechat.png'),
Image.network('https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'),
Image.network(
'https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
width: 300,
height: 200,
)
],
);
效果如下:

写法也很简单,就是设置一下 children 属性就可以了。
然后里面的 Widget 数组填充我们要展示的 Widget 即可。
上面说了刘海屏设备顶部会看不到,那怎么办?
2)mainAxisAlignment
mainAxisAlignment 你可以认为是主轴的对齐方式。对于竖直的 Column,那就是竖直方向的对齐。
影响整个 Column
因此可以设置如下:
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset('assets/images/wechat.png'),
Image.network('https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'),
Image.network(
'https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
width: 300,
height: 200,
)
],
);
你就会发现整个 Column 在竖直方向都居中了。

3)crossAxisAlignment
crossAxisAlignment 你可以认为是交叉轴的对齐方式,对于竖直的 Column,那就是水平方向的对齐。
影响 Column 里面的每一个 Widget
设置如下:
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Image.asset('assets/images/wechat.png'),
Image.network('https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'),
Image.network(
'https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
width: 300,
height: 200,
)
],
);
你会发现原本最后一张居中的图片在水平方向向右边对齐。

4. Row
1)基本使用
/// Creates a horizontal array of children.
大概意思是创建一组水平的子组件集合,可以联想到 LinearLayout 里面的 orientation 设置为 horizontal 时的布局。
也可以记忆为 Row 代表行,因此只有一行。
如下:

Sample:
return Row(
children: <Widget>[
Text('Widget One', style: TextStyle(color: Colors.blue),),
Text('Widget Two'),
],
);
效果如下:

可以看到只有一行,所以使用 Row。
写法也是比较简单,就是设置一下 children 属性就可以了。
然后里面的 Widget 数组填充我们要展示的 Widget 即可。
2)mainAxisAlignment
mainAxisAlignment 你可以认为是主轴的对齐方式,对于水平的 Row,那就是水平方向的对齐。
影响整个 Row
因此可以设置如下:
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Widget One', style: TextStyle(color: Colors.blue),),
Text('Widget Two'),
],
);
这样效果显示就是上图居中。

3)crossAxisAlignment
crossAxisAlignment 你可以认为是交叉轴的对齐方式,对于水平的 Row,那就是竖直方向的对齐。
影响 Row 里面的每一个 Widget
设置如下:(这里引入了一个后面才会讲到的 Widget,大家可以暂时不理,看下效果)
return Container(
width: 300,
height: 300,
color: Colors.grey,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.blue,
child: Text(
'Widget One',
),
),
Container(
width: 100,
height: 100,
color: Colors.yellow,
child: Text(
'Widget Two',
),
),
],
),
);
灰色是我们的父容器,可以看到两个控件水平方面居中,竖直方面向下对齐。

5. Container
Container 的使用超级广泛。
我们这里略微讲一下一些使用场景。
1)给一些没有自带宽高的属性设置宽高。
比如我们上面讲到 Row 最后一个 Sample 的时候,给 Text、Row 设置宽高都是在外面套一层 Container。
- 设置间距。
以上面 Column 的三张图片为例,他们一开始是下面代码:
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset('assets/images/wechat.png'),
Image.network('https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'),
Image.network(
'https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
width: 300,
height: 200,
)
],
);
效果如下:

我们希望第一张和第二张图片有点距离,可以这样设置:
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset('assets/images/wechat.png'),
Container(
padding: EdgeInsets.only(top: 20.0),
child: Image.network('https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'),
),
Image.network(
'https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
width: 300,
height: 200,
)
],
);
效果如下:

我们代码里面使用 Container 都是把 Widget 拿出来作为 Container 的 child。
这里的 padding 使用有三种常用写法:
第一种:上下左右 padding 的值都一样
源码:
const EdgeInsets.all(double value)
: left = value, top = value, right = value, bottom = value;
第二种:上下左右 padding 不一致或者只想设置某一个或某几个方向
源码:
const EdgeInsets.only({
this.left = 0.0,
this.top = 0.0,
this.right = 0.0,
this.bottom = 0.0
});
第三种:设置水平或者垂直方向的 padding
源码:
const EdgeInsets.symmetric({ double vertical = 0.0,
double horizontal = 0.0 })
: left = horizontal, top = vertical, right = horizontal, bottom = vertical;
相信现在给出源码,大家都知道怎么写了。
记得花括号是可选参数哈~
Sample:
padding: EdgeInsets.all(left : 20.0),
padding: EdgeInsets.only(left : 20.0),
padding: EdgeInsets.symmetric(horizontal : 20.0),
margin 和 padding 也是类似的,区别相信学过 Android 的都知道,你也可以自己测试一下区别,这里就不赘余了。
另外注意 Container 源码有个注释:
/// The `height` and `width` values include the padding.
举个例子就是假设有一张图片宽 100,假设你左右预留 padding 10,那么你宽需要设置为 120。
6. SizedBox
你可以用来替换需要套一层 Container 来设置 margin 或者 padding 的 Widget。
比如上面的代码
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset('assets/images/wechat.png'),
Container(
padding: EdgeInsets.only(top: 20.0),
child: Image.network('https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'),
),
Image.network(
'https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
width: 300,
height: 200,
)
],
);
可以等效替换为
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset('assets/images/wechat.png'),
SizedBox(
height: 20.0,
),
Image.network('https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'),
Image.network(
'https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
width: 300,
height: 200,
)
],
);
将
Container(
padding: EdgeInsets.only(top: 20.0),
child: Image.network('https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'),
),
替换成了
SizedBox(
height: 20.0,
),
Image.network('https://upload-images.jianshu.io/upload_images/5361063-cfad13c672a06084.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'),
当然这里由于 Widget 没有限制宽高,所以 padding 或者 margin 在这里起到一样作用。
严格来说 SizedBox 应该是替换 margin。替换 padding 需要注意上面说的宽高影响。
常用的 Widget 我们就介绍到这里。
其他的我们后续再介绍或者大家自行查阅官网 Widget 集合。
相信现在的你可以根据官网的 Sample 和说明以及亲自测试快速掌握新 Widget 的使用。
官网 Widget 集合:
https://flutter.dev/docs/development/ui/widgets
更多阅读:
Flutter 即学即用系列博客——01 环境搭建
Flutter 即学即用系列博客——02 一个纯 Flutter Demo 说明
Flutter 即学即用系列博客——03 在旧有项目引入 Flutter
Flutter 即学即用系列博客——04 Flutter UI 初窥
Flutter 即学即用系列博客——05 StatelessWidget vs StatefulWidget

Flutter 即学即用系列博客——06 超实用 Widget 集锦的更多相关文章
- 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 即学即用系列博客——03 在旧有项目引入 Flutter
前言 其实如果打算在实际项目中引入 Flutter,完全将旧有项目改造成纯 Flutter 项目的可能性比较小,更多的是在旧有项目引入 Flutter. 因此本篇我们就说一说如何在旧有项目引入 Flu ...
- Flutter 即学即用系列博客——10 混淆
前言 之前的博客我们都是在 debug 的模式下进行开发的. 实际发布到市场或者给到用户的都是 release 包. 而对于 Android 来说,release 包一个重要的步骤就是混淆. Andr ...
- Flutter 即学即用系列博客——02 一个纯 Flutter Demo 说明
前言 上一篇文章我们搭建好了 Flutter 的开发环境. Flutter 即学即用--01 环境搭建 这一篇我们通过 Flutter 的一个 Demo 来了解下 Flutter. 开发系统:MAC ...
随机推荐
- BZOJ1500 [NOI2005]维修数列-fhq_Treap
题面见这里 反正是道平衡树,就拿 fhq_Treap 写了写... 这道题思路基本是围绕“用 Treap 维护中序遍历” 和 中序遍历的性质 来进行的操作 所以就可以类比线段树进行一些操作 1. 建树 ...
- TensorFlow之DNN(二):全连接神经网络的加速技巧(Xavier初始化、Adam、Batch Norm、学习率衰减与梯度截断)
在上一篇博客<TensorFlow之DNN(一):构建“裸机版”全连接神经网络>中,我整理了一个用TensorFlow实现的简单全连接神经网络模型,没有运用加速技巧(小批量梯度下降不算哦) ...
- Unix中的I/O模型
本文所指的I/O均是网络I/O. 一. POSIX对同步.异步I/O的定义 我们先大致看看POSIX对同步.异步的定义,不用细究,重点看我标红的部分就行. 同步I/O会导致请求进程阻塞,直到I/O操作 ...
- 开源)嗨,Java,你可以生成金山词霸的二维码分享海报吗?
As long as you can still grab a breath, you fight.只要一息尚存,就不得不战. 有那么一段时间,我特别迷恋金山词霸的每日一句分享海报.因为不仅海报上的图 ...
- gulp、browsersync代理跨域
//gulpfile.js "use strict"; const gulp = require("gulp"), newer = require(" ...
- 神经网络——反向传播BP算法公式推导
在神经网络中,当我们的网络层数越来越多时,网络的参数也越来越多,如何对网络进行训练呢?我们需要一种强大的算法,无论网络多复杂,都能够有效的进行训练.在众多的训练算法中,其中最杰出的代表就是BP算法,它 ...
- Win10+RTX2080深度学习环境搭建:tensorflow、mxnet、pytorch、caffe
目录 准备工作 设置conda国内镜像源 conda 深度学习环境 tensorflow.mxnet.pytorch安装 tensorflow mxnet pytorch Caffe安装 配置文件修改 ...
- [翻译 EF Core in Action 1.10] 应该在项目中使用EF Core吗?
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- POLARDB · 最佳实践 · POLARDB不得不知道的秘密(二)
前言 POLARDB For MySQL(下文简称POLARDB)目前是阿里云数据库团队主推的关系型数据库.线上已经有很多企业用户在使用并且稳定运行了很久.当然,由于POLARDB是为云上环境专门打造 ...
- headfirst设计模式(8)—适配器模式与外观模式
前言 这一章主要讲2个模式,一个是,适配器模式(负责将一个类的接口适配成用户所期待的),另外一个是外观模式(为子系统提供一个共同的对外接口),看完的第一反应是,为什么要把它们两放在同一章,难道它们有什 ...