效果图

image-20220911202033301

代码实现

1
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
class MyPage extends StatelessWidget {
MyPage({Key? key}) : super(key: key);
Widget titleSection = Container(//自定义组件,标题部分,即头部部分
padding: const EdgeInsets.all(32),
child: Row(//一行
children: [//三列
Expanded(//第一列,标题和副标题
child: Column(//第一列有两行
crossAxisAlignment: CrossAxisAlignment.start,//交叉轴方向,此处即水平方向对齐方式,在起点处对齐,即左对齐
children: [
const Text(//第一行
"Hello,this is Alice!",
style: TextStyle(
fontWeight: FontWeight.bold,//加粗,表明主体
),
),
Text(//第二行
"Good evening!",
style: TextStyle(
color: Colors.grey[500],//灰色
),
)
],
),
),
const LikeWidget(),//这是下面写的自定义有状态组件
],
),
);
Widget options=Container(//自定义组件,操作栏部分
margin: const EdgeInsets.only(top: 10),
child: Row(//一行三列
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [//三列
Column(//第一列,图标加文字描述,下同
children: const [
Icon(
Icons.call,
color: Colors.blue,
),
Text(
"CALL",
style: TextStyle(
color: Colors.blue,
),
)
],
),
Column(//第二列
children: const [
Icon(
Icons.route,
color: Colors.blue,
),
Text(
"ROUTE",
style: TextStyle(
color: Colors.blue,
),
)
],
),
Column(//第三列
children: const [
Icon(
Icons.share,
color: Colors.blue,
),
Text(
"SHARE",
style: TextStyle(
color: Colors.blue,
),
)
],
),
],
),
);
Widget text=Container(//自定义组件,文本区域部分
margin: const EdgeInsets.only(top: 10),
padding: const EdgeInsets.all(30),//内边距30,即四周留空
child: const Text(
"Something exciting happened when I got up this day. Maybe, but I am not sure about the time."
),
);
@override
Widget build(BuildContext context) {
return Column(
children: [
Image.asset(//预设图片
'images/Alice.jpg',
// width: 100,
height: 300,
fit: BoxFit.cover,//填充方式,覆盖。
),
titleSection,
options,
text
],
) ;
}
}

class LikeWidget extends StatefulWidget {//这个是有状态组件的显示部分
const LikeWidget({Key? key}) : super(key: key);

@override
State<LikeWidget> createState() => _LikeWidgetState();
}

class _LikeWidgetState extends State<LikeWidget> {//这个是有状态组件的状态部分
bool _like=true;
int _count=41;

void _clickLike(){
setState(() {//有状态组件通过执行setState()执行组件的重新渲染,传入的参数是一个自定义函数
if(_like){
_like=false;
_count--;
}
else{
_like=true;
_count++;
}
});
}

@override
Widget build(BuildContext context) {//写组件的内容,该咋写咋写,值换动态的就行了
return Row(
children: [
IconButton(
icon: _like?const Icon(Icons.star,color: Colors.red,):const Icon(Icons.star_border,color: Colors.red,),
onPressed: _clickLike,
),
Text(
"$_count"
)
],
);
}
}

总结

  • 无状态组件自身无法改变,根据我的理解,它是那种事先就决定好的内容,无法在程序运行时做更改,比如Text,Icon,IconButton
  • 有状态组件自身可以更改,通过提前设定状态量,就可以在用户交互的时候,改变状态量,重新渲染组件,比如CheckBox,Radio
  • 有状态组件的显示部分和状态部分是分开的,build在状态部分中
  • 有状态组件通过setState()函数来重新渲染组件