
# 1. Widget
Flutter核心思想是用 widget 来构建你的 UI 界面。 Widget 描述了在当前的配置和状态下视图所应该呈现的样子。当 widget 的状态改变时,它会重新构建其描述(展示的 UI),框架则会对比前后变化的不同,以确定底层渲染树从一个状态转换到下一个状态所需的最小更改。
在Flutter中,widget分为两类:Stateful(有状态)和 stateless(无状态)widget。
# 1.1 StatelessWidget
StatelessWidget没有内部状态,Icon、IconButton, 和Text都是无状态widget, 它们都是 StatelessWidget的子类。
# 1.2 StatefulWidget
StatefulWidget是动态的,用户可以和其交互(例如输入一个表单、 或者移动一个slider滑块),或者可以随时间改变 (也许是数据改变导致的UI更新)。Checkbox, Radio, Slider, InkWell, Form, and TextField 都是 stateful widgets, 它们都是 StatefulWidget的子类。
创建一个有状态的widget需要进行以下操作:
要创建一个自定义有状态widget,需创建两个类:StatefulWidget和State。
定义一个widget类,继承自StatefulWidget。
子State,包含该widget状态并定义该widget build()方法的类,它继承自State。
状态对象包含widget的状态和build() 方法。
当widget的状态改变时,状态对象调用setState(),告诉框架重绘widget
# 2. Hello World
- Demo Code
import "package:flutter/material.dart";
void main() {
runApp(const HelloWorld());
}
class HelloWorld extends StatelessWidget {
const HelloWorld({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('ApeGeek'),
),
body: const Center(
child: Text(
"Hello World !",
style: TextStyle(fontSize: 22, color: Colors.red),
overflow: TextOverflow.fade,
))),
);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- rendering

# 3. StatelessWidget
# 3.1 Text
Text widget 可以用来在应用内创建带样式的文本。
# 3.1.1 定义
const Text(
String this.data, {
Key? key,
this.style,
this.strutStyle,
this.textAlign,
this.textDirection,
this.locale,
this.softWrap,
this.overflow,
this.textScaleFactor,
this.maxLines,
this.semanticsLabel,
this.textWidthBasis,
this.textHeightBehavior,
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 3.2 Row
Row 是一个可以沿水平方向展示它的子组件的组件。
它还可以灵活布局,如果要让某个子组件填充满剩余剩余空间,请使用 Expanded 组件包裹该组件即可。
Row 组件是不可以滚动的,所以在 Row 组件中一般不会放置过多子组件,如果需要滚动的话应该考虑使用 ListView。
# 3.2.1 定义
Row({
Key? key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection? textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline? textBaseline, // NO DEFAULT: we don't know what the text's baseline should be
List<Widget> children = const <Widget>[],
}) : super(
children: children,
key: key,
direction: Axis.horizontal,
mainAxisAlignment: mainAxisAlignment,
mainAxisSize: mainAxisSize,
crossAxisAlignment: crossAxisAlignment,
textDirection: textDirection,
verticalDirection: verticalDirection,
textBaseline: textBaseline,
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 3.2.2 常用属性
crossAxisAlignment:子组件沿着 Cross 轴(在 Row 中是纵轴)如何摆放,其实就是子组件对齐方式,可选值有:
- CrossAxisAlignment.start:子组件在 Row 中顶部对齐。
- CrossAxisAlignment.end:子组件在 Row 中底部对齐。
- CrossAxisAlignment.center:子组件在 Row 中居中对齐。
- CrossAxisAlignment.stretch:拉伸填充满父布局。
- CrossAxisAlignment.baseline:在 Row 组件中会报错。
mainAxisAlignment:子组件沿着 Main 轴(在 Row 中是横轴)如何摆放,其实就是子组件排列方式,可选值有:
- MainAxisAlignment.start:靠左排列。
- MainAxisAlignment.end:靠右排列。
- MainAxisAlignment.center:居中排列。
- MainAxisAlignment.spaceAround:每个子组件左右间隔相等,也就是 margin 相等。
- MainAxisAlignment.spaceBetween:两端对齐,也就是第一个子组件靠左,最后一个子组件靠右,剩余组件在中间平均分散排列。
- MainAxisAlignment.spaceEvenly:每个子组件平均分散排列,也就是宽度相等。
mainAxisSize:Main 轴大小,可选值有:
- MainAxisSize.max:相当于 Android 的 match_parent。
- MainAxisSize.min:相当于 Android 的 wrap_content。
textBaseline:不太理解。
textDirection:子组件排列顺序,可选值有:
- TextDirection.ltr:从左往右开始排列。
- TextDirection.rtl:从右往左开始排列。
verticalDirection:确定如何在垂直方向摆放子组件,以及如何解释 start 和 end,指定 height 可以看到效果,可选值有:
- VerticalDirection.up:Row 从下至上开始摆放子组件,此时我们看到的底部其实是顶部。
- VerticalDirection.down:Row 从上至下开始摆放子组件,此时我们看到的顶部就是顶部。
children:子组件,值是一个 Widget 数组。
# 3.2.3 Demo Code
import "package:flutter/material.dart";
class MyRow extends StatelessWidget {
const MyRow({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
title: "Row Test",
home: Scaffold(
appBar: AppBar(
title: const Text("Row Demo"),
),
body: Row(
children: [
Expanded(
flex: 3,
child: Container(
color: Colors.red,
height: 50,
child: const Text(
"Row 1",
textAlign: TextAlign.center,
),
),
),
Expanded(
flex: 2,
child: Container(
height: 50,
color: Colors.amber,
child: const Text("Row 2"),
),
),
Expanded(
flex: 1,
child: Container(
height: 50,
color: Colors.blue,
child: const Text("Row 3"),
),
),
],
)),
);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 3.2.4 效果图

# 3.3 Column
Column可以在垂直方向排列其子组件。参数和Row一样,不同的是子组件的布局方向为垂直,主轴和纵轴相对于Row正好相反。
# 3.3.1 定义
# 3.3.2 常用属性
# 3.3.3 Demo Code
import "package:flutter/material.dart";
class MyColumn extends StatelessWidget {
const MyColumn(Key? key) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text(
"Column Demo",
),
),
body: Column(
children: [
const Text(
"this is demo",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
Image.asset("images/demo/gyy.jpeg"),
Container(
height: 50,
color: Colors.blue,
alignment: Alignment.center,
child: const Text(
"this is container",
),
),
],
),
),
);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 3.3.4 效果图

# 3.2.3 Expanded
class Expanded extends Flexible {
/// Creates a widget that expands a child of a [Row], [Column], or [Flex]
/// so that the child fills the available space along the flex widget's
/// main axis.
const Expanded({
Key? key,
int flex = 1,
required Widget child,
}) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
}
2
3
4
5
6
7
8
9
10
# 3.3 Stack
Stack widget 不是线性(水平或垂直)定位的,而是按照绘制顺序将 widget 堆叠在一起。你可以用 Positioned widget 作为Stack 的子 widget,以相对于 Stack 的上,右,下,左来定位它们。 Stack 是基于 Web 中的绝对位置布局模型设计的。
# 3.4 Container
Container widget 可以用来创建一个可见的矩形元素。 Container 可以使用 BoxDecoration 来进行装饰,如背景,边框,或阴影等。 Container 还可以设置外边距、内边距和尺寸的约束条件等。另外,Container可以使用矩阵在三维空间进行转换。