Flutter

基本概念

Vue 中的组件在这里叫做 Widget,组件可以包含组件,组件可以通过继承实现快速构建;组件通过内置的 build 方法来实现渲染,有点像小程序中的 setData;组件也有一些内置的属性,用来设置组件的相关信息,例如标题,主体等;

官方的 Material 组件库里面有很多前人写好的组件,可以用来快速构建应用;这些组件自带样式,可以自适应不同的终端,非常方便;有些组件甚至可以只负责样式,然后再内置包含内容的其他组件,很灵活,实现了样式和内容的解耦;

有个 pubspec.yaml 文件很像 nodejs 里面的 package.json 文件,用来定义项目的相关信息以及依赖的库;同时还有一个 pub.dev 仓库网站,类似 nodejs 里面的 npm 仓库,可以方便的实现第三方库的集中管理和下载;另外还有一个 pubspec.lock 文件,貌似也跟 nodejs 里面的 package_json.lock 功能差不多;

flutter pub 命令很像 npm ,用来管理包,例如 flutter pub get 类似 npm install,用来安装依赖文件中指定的各种包,flutter pub add 则用来添加包(发现添加后,好像并没有自动下载,而是需要再运行一下 pub get 才行,但是看 pub.dev 网站的文档好像只需要 add 就可以了);

StateLessWidget 表示无状态的应用,即生成后里面的数据就不可变了;如果里面的数据需要可变的,则需要使用 StatefulWidget;但是很有意思的是 StatefulWidget 的实现是在它里面再包含一个 State 类来实现的可变状态(猜测这样是为了兼容性?);

通过在类名添加下划线前缀,在 Dart 中表示强制私有;在创建 StatefulWidget 时,编辑器自动创建的 State 类即默认为私有的;

创建 State 时,有一个很有意思的点,即新创建的 state 并不是直接继承某个 StateWidget 来实现的,而是给 State 传递一个 StatefulWidegt 来实现,示例如下:

1
2
class _RandomWordsState extends State<RandomWords>  {}
// 此处的 RandomWords 是一个 StatefulWidget

Widget 类有一个内置的 build 方法,用来初始化对象,一般继承父类后,会通过重写 build 方法覆盖父类的方法;

StatefulWidget 类有一个内置的 createState 方法,用来初始化 State 对象,通过对其进行重写,实现自定义的 State;

在类内部定义的函数,直接就是该类的方法,如果加上下划线作为前缀,则成为该类的私有方法;

ListView 有一个内置的 itemBuilder 方法,貌似列表滚动到底后,会自动触发该方法;

布局

在 Flutter 里面,一切均是 Widget,它既负责展示,也负责交互,很像 Vue 里面的组件;

通常来说,内置的组件已经设定好了默认样式;如果想修改这些默认样式,例如 margin, padding, border, backgroud 等,有两种方法:

  • 通过外加一层 Container 的 Widget 来实现,自定义的样式放在 Container 当中去实现,同时将内置 Widget 放在 Container 中,而不是去修改内置 Widget,这样实现了更好的解耦,也方便将来进行统一的管理,例如当更新某些全局设置时,所有内置 Widget 都会相应更新,而不会因为自行修改导致失效;
  • 直接修改 Widget 的相关属性来实现,例如 color, font, weight 等;

有一些 widget 是专门负责布局排版的,统称为 layout widget,主要有以下三类:

  • single-child:只包含一个子元素;
  • multi-child:包含多个子元素;
  • silver:其他一些类型;

所有的 layout widget 不外乎使用以下两种方式中的一种来添加子元素

  • child :仅有单个子元素,例如 Center,Container 等;
  • children :拥有多个子元素,例如 Row,Column,ListView 或 Stack 等;

大部分 Widget 都有一个 build 方法,当该方法被调用时,将生成界面;

常用 Widget

Scaffold:包含顶部标题栏,标题,背景色等元素;

Row:表示一行,里面可以嵌套各种东西;

Column:表示一列,里面可以嵌套各种东西;

Row 或 Column 内部元素的对齐,通过其属性 mainAxisAllignment 和 crossAxisAlignment 来实现;

1
2
3
4
5
6
7
8
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset('images/pic1.jpg'),
Image.asset('images/pic2.jpg'),
Image.asset('images/pic3.jpg'),
],
);

如果图片的大小跟所设定的区域尺寸不匹配,可通过将其放到 Expanded 中,来实现自动缩放,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Image.asset('images/pic1.jpg'),
),
Expanded(
child: Image.asset('images/pic2.jpg'),
),
Expanded(
child: Image.asset('images/pic3.jpg'),
),
],
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Image.asset('images/pic1.jpg'),
),
Expanded(
flex: 2,
child: Image.asset('images/pic2.jpg'),
),
Expanded(
child: Image.asset('images/pic3.jpg'),
),
],
);

默认情况下,Row 或 Column 内部的元素会占据整行或整列的空间,如果需要各个元素按指定尺寸挨着显示,则可以通过设置 mainAxisSize 来实现

1
2
3
4
5
6
7
8
9
10
Row(
mainAxisSize: MainAxisSize.min, // 设置尺寸
children: [
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
const Icon(Icons.star, color: Colors.black),
const Icon(Icons.star, color: Colors.black),
],
)

Flutter
https://ccw1078.github.io/2022/01/01/Flutter/
作者
ccw
发布于
2022年1月1日
许可协议