一、Widget
1.1 基础类Widget
- Text
构造方式 | 说明 |
---|---|
Text(data,{...}) | data:文本文案,{...}:可选命名参数 |
Text(textSpan,{...}) | textSpan:文本片段,{...}:可选命名参数 |
第一个相对简单,满足一般使用场景。
第二个更加灵活,可对文本文案做一些深度定制,比如添加中划线、下划线、一部分文案改颜色这样的需求,就必须使用textSpan对文本做处理了。 下面按照由简单到复杂的步骤逐步使用Text来呈现不一样的文本信息 首先,假设有这么一段文本,需要展示在屏幕上:String data = "2018年江苏省GDP增长情况:苏州涨幅最高(8%),徐州增速最快(2%提升到6%),镇江出现下滑(-3%),详细信息参考官网。" 复制代码
不做任何处理的文案展示:
@override Widget build(BuildContext context) { String data = "2018年江苏省GDP增长情况:苏州涨幅最高(8%),徐州增速最快(2%提升到6%),镇江出现下滑(-3%),详细信息参考官网。"; return Scaffold( appBar: AppBar( title: Text("Text"), ), body: new Column( mainAxisSize: MainAxisSize.max, //主轴方向充满屏幕 mainAxisAlignment: MainAxisAlignment.start, //子widget左对齐 crossAxisAlignment: CrossAxisAlignment.start, //子widget在纵轴方向居中对齐 children:[ Text(data ), ], ), ); }复制代码
老板说:最多显示一行,显示不下的地方用...结尾,必须字体需要放大 加粗:
这个时候就需要使用构造函数中的命名参数来设置了@override Widget build(BuildContext context) { String data = "2018年江苏省GDP增长情况:苏州涨幅最高(8%),徐州增速最快(2%提升到6%),镇江出现下滑(-3%),详细信息参考官网。"; return Scaffold( body: new Column( children:[ Text(data , maxLines: 1, //最多显示1行 overflow: TextOverflow.ellipsis, //末尾截断 style: TextStyle( fontSize: 16, //字体大小 fontWeight: FontWeight.bold //加粗 ),), ], ), ); }复制代码
老板又说:这样显示没有突出点。需要将苏州标红,镇江标绿,题干加粗,最后可以点击打开官网......:
一段话需要设置这么多的状态,这就需要用到第二种构造方式了:@override Widget build(BuildContext context) { return Scaffold( body: new Column( children:[ Text.rich( TextSpan(children: [ TextSpan( text: "2018年江苏省GDP增长情况: ", style: TextStyle(fontWeight: FontWeight.bold)), TextSpan( text: "苏州涨幅最高", ), TextSpan( text: "(8%)", style: TextStyle(color: Colors.deepOrange), //颜色设置为红色 ), TextSpan( text: ",徐州增速最快", ), TextSpan( text: "(2%提升到6%)", style: TextStyle(color: Colors.yellow), //颜色设置为黄色 ), TextSpan( text: ",镇江出现下滑", ), TextSpan( text: "(-3%), ", style: TextStyle(color: Colors.green), //颜色设置为绿色 ), TextSpan( text: "详细信息参考官网。", style: TextStyle( color: Colors.grey, decoration: TextDecoration.underline),//颜色设置为灰色,下划线 recognizer: new TapGestureRecognizer() //设置点击事件 ..onTap = () { print("打开官网"); }), ]), ), ], ), ); }复制代码
Text的命名参数有很多,这里就不一一举例实现了。万变不离其宗,所有的变化都是通过2个构造函数中的textSpan和可选命名构造函数实现的,附一张Text可选命名参数的简要说明:
参数名 | 含义 | 类型 | 说明 |
---|---|---|---|
style | 字体属性 | TextStyle | 通过对象TextStyle获取,TextStyle构造函数也接收一堆可选命名参数 |
textAlign | 文字对其方式 | TextAlign | 通过枚举TextAlign获取 |
textDirection | 文字方向 | TextDirection | 通过枚举TextDirection获取,多数情况下不需要关心这个参数 |
locale | 国际化语言相关 | Locale | |
softWrap | 是否自动换行 | bool | 若为false,文字将不考虑容器大小,单行显示,超出屏幕部分将默认截断处理 |
overflow | 文字长度超过容器的处理方式 | TextOverflow | 通过枚举TextOverflow获取 |
textScaleFactor | 相对于当前字体大小的缩放因子 | double | 默认值将为1.0 |
maxLines | 文字最大行数 | int | 默认不限制 |
semanticsLabel | 图像的语义描述,用于向Andoid上的TalkBack和iOS上的VoiceOver提供图像描述 | String | 没搞明白这个参数 |
- Button Button比较简单,这里列举三个最简单的实现:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Button"), ), body: new Column( children:[ RaisedButton( child: Text("RaisedButton"), onPressed: () { //点击事件监听 }, ), FlatButton( child: Text("FlatButton"), onPressed: () { //点击事件监听 }, ), OutlineButton( child: Text("OutlineButton"), onPressed: () { //点击事件监听 }, ), ], ), ); }复制代码
- Image
-
通过assets加载图片:
- step1: 项目根目录新建存放图片的目录。 我的目录名为images(名称随意)
- step2: 在pubspec.yml中配置图片
- step3: 代码中获取图片
-
网络下载图片
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Image & Icon"), ), body: new Column( children:[ Image( //加载asset图片,大小100*100 width: 100, height: 100, image: AssetImage("images/test_img.jpg"), ), Image( //加载网络图片,大小200*200 width: 200, height: 200, image: NetworkImage("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1547637189125&di=36a042b71b1e6b4ccd80adca6d8f05ff&imgtype=0&src=http%3A%2F%2Fimg.bimg.126.net%2Fphoto%2FZZ5EGyuUCp9hBPk6_s4Ehg%3D%3D%2F5727171351132208489.jpg"), ), ], ), ); }复制代码
效果图:
- Icon
- Switch
- Checkbox。
- TextField
1.2 布局类Widget
布局类widget一般包含多个children,布局类widget一般是描述children的排列方式
Widget | 含义 | 说明 |
---|---|---|
Row | 行布局,一行多列 | |
Wrap | Row默认只有一行,如果超出屏幕不会折行。通过Wrap可以让Row溢出部分自动折行 | |
Column | 列布局,一列多行 | |
Flow | 使用较少 | |
Flex | 可以定义权重的Row或者Column(个人觉得类似android中的weight属性) | Flex需要和Expanded配合使用 |
Stack | 层叠布局,类似FrameLayout | Stack本身有属性设置children的默认对其方式,也可以使用Positioned准确定义child的位置 |
- 共有参数
参数名 | 含义 | 备注 |
---|---|---|
textDirection | 表示水平方向子widget的布局顺序(是从左往右还是从右往左),默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左)。 | |
mainAxisSize | 表示Row在主轴(水平)方向占用的空间,默认是MainAxisSize.max,表示尽可能多的占用水平方向的空间,此时无论子widgets实际占用多少水平空间,Row的宽度始终等于水平方向的最大宽度;而MainAxisSize.min表示尽可能少的占用水平空间,当子widgets没有占满水平剩余空间,则Row的实际宽度等于所有子widgets占用的的水平空间 | |
mainAxisAlignment | 表示子Widgets在Row所占用的水平空间内对齐方式,如果mainAxisSize值为MainAxisSize.min,则此属性无意义,因为子widgets的宽度等于Row的宽度。只有当mainAxisSize的值为MainAxisSize.max时,此属性才有意义,MainAxisAlignment.start表示沿textDirection的初始方向对齐,如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。而MainAxisAlignment.end和MainAxisAlignment.start正好相反;MainAxisAlignment.center表示居中对齐。读者可以这么理解:textDirection是mainAxisAlignment的参考系。 | |
verticalDirection | 表示Row纵轴(垂直)的对齐方向,默认是VerticalDirection.down,表示从上到下 | |
crossAxisAlignment | 表示子Widgets在纵轴方向的对齐方式,Row的高度等于子Widgets中最高的子元素高度,它的取值和MainAxisAlignment一样(包含start、end、 center三个值),不同的是crossAxisAlignment的参考系是verticalDirection,即verticalDirection值为VerticalDirection.down时crossAxisAlignment.start指顶部对齐,verticalDirection值为VerticalDirection.up时,crossAxisAlignment.start指底部对齐;而crossAxisAlignment.end和crossAxisAlignment.start正好相反 | |
children | 子Widgets数组。 |
- Wrap特有参数
参数名 | 含义 | 备注 |
---|---|---|
spacing | 主轴方向子widget的间距 | |
runSpacing | 纵轴方向的间距 | |
runAlignment | 纵轴方向的对齐方式 |
- Stack特有参数
参数名 | 含义 | 备注 |
---|---|---|
alignment | 此参数决定如何去对齐没有定位(没有使用Positioned)或部分定位的子widget。所谓部分定位,在这里特指没有在某一个轴上定位:left、right为横轴,top、bottom为纵轴,只要包含某个轴上的一个定位属性就算在该轴上有定位。 | |
fix | 此参数用于决定没有定位的子widget如何去适应Stack的大小。StackFit.loose表示使用子widget的大小,StackFit.expand表示扩伸到Stack的大小。 | |
overflow | 此属性决定如何显示超出Stack显示空间的子widget,值为Overflow.clip时,超出部分会被剪裁(隐藏),值为Overflow.visible 时则不会。 |
1.3 容器类Widget
容器类widget一般只有1个child。容器的描述一般是对child的包装:添加一些修饰(补白或背景色等)、变换(旋转或剪裁等)、或限制(大小等)。
参数名 | 含义 | 备注 |
---|---|---|
Padding | 给其子节点添加补白(填充) | EdgeInsets.all .fromLTRB .only .symmetric |
ConstrainedBox | ConstrainedBox用于对齐子widget添加额外的约束 | 宽高、最小宽高、最大宽高 |
SizedBox | 可以看出是一个固定了宽高的ConstrainedBox | ConstrainedBox如果有多重限制会发生什么? |
UnconstrainedBox | UnconstrainedBox不会对子Widget产生任何限制,它允许其子Widget按照其本身大小绘制 | 会很少直接使用此widget |
DecoratedBox | DecoratedBox可以在其子widget绘制前(或后)绘制一个装饰Decoration(如背景、前景、边框、渐变、阴影等) | |
Transform | 平移、旋转、缩放等 | 有一个RotatedBox,需要区分和 Transform.rotate的区别,一个在绘制时起作用,一个在布局时起作用 |
Container | 可以看成是其他容器类widget的一个组合 | Container可以实现同时需要填充、约束、装饰、变换等场景 |
Scaffold | 一个路由页的骨架,可以非常容易的拼装出一个完整的页面 | AppBar、抽屉、顶部导航、底部导航、悬浮按钮等等 |
1.4 功能类Widget
1.5 事件处理与监听
1.6 动画
1.7 自定义
其他
flutter的一些开源库:
- loading态widget: https://pub.flutter-io.cn/packages/flutter_spinkit