一、Flutter架构
flutter官方文档:https://api.flutter.dev/flutter/widgets/widgets-library.html
flutter架构:
在flutter的世界里,包括views,view controllers,layouts等在内的概念都建立在Widget之上。widget是flutter功能的抽象描述。通过组合不同的 Widget,来实现我们用户交互界面。
Widget 分为两种:
1、无状态的,StatelessWidget,它只能用来展示信息,不能有动作(用户交互)
使用方法:继承 StatelessWidget,实现 build 方法
class FooWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// ...
}
}
2、有状态的,StatefulWidget,可以通过改变状态使 UI 发生变化,包含用户交互。
使用方法:稍微复杂,需要一个 State,例子如下
class BarWidget extends StatefulWidget {
@override
State createState() {
return _BarWidgetState();
}
}
class _BarWidgetState extends State {
@override
Widget build(BuildContext context) {
// ...
}
}
二、文本Text
使用 TextStyle,可以对文本的样式进行修改
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text(
"Put your text here",
textAlign: TextAlign.center,
maxLines: 1,
style: TextStyle(
color: Colors.blue,
fontSize: 16.0,
fontWeight: FontWeight.bold
),
);
}
}
三、图片Image
Flutter中的图片缩放是fit字段来控制的,缩放属性值在BoxFit枚举中。
有:fill、contain、cover,fitWidth、fitHeight、none、scaleDown
图片的来源:网络、文件、资源和内存
Image.asset(name);
Image.file(file);
Image.memory(bytes);
Image.network(src);
例子:
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Image.network(
'https://gw.alicdn.com/tfs/TB1CgtkJeuSBuNjy1XcXXcYjFXa-906-520.png',
fit: BoxFit.contain,
width: 150.0,
height: 100.0,
);
}
}
四、按钮FlatButton 和 RaisedButton
两种按钮的区别在于样式不同。child 参数用于设置按钮的内容。它可以接受任意的 Widget,比方说,Text,Image;
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
var flatBtn = FlatButton(
onPressed: () => print('FlatButton pressed'),
child: Text('BUTTON'),
);
var raisedButton = RaisedButton(
onPressed: () => print('RaisedButton pressed'),
child: Text('BUTTON'),
);
return raisedButton;
}
}
五、文本输入框TextField
为了获取用户输入的文本,我们需要给他设置一个 controller。通过这个 controller,就可以拿到文本框里的内容
class MessageForm extends StatefulWidget {
@override
State createState() {
return _MessageFormState();
}
}
class _MessageFormState extends State {
var editController = TextEditingController();
@override
Widget build(BuildContext context) {
// Row、Expand 都是用于布局的控件,这里可以先忽略它们
return Row(
children: [
// 占满一行里除 RaisedButton 外的所有空间
Expanded(
child: TextField(
controller: editController,
),
),
RaisedButton(
child: Text("click"),
onPressed: () => print('text inputted: ${editController.text}'),
)
],
);
}
@override
void dispose() {
super.dispose();
// 手动调用 controller 的 dispose 方法以释放资源
editController.dispose();
}
}
六、显示弹框
RaisedButton(
child: Text("click"),
onPressed: () {
showDialog(
// 第一个 context 是参数名,第二个 context 是 State 的成员变量
context: context,
builder: (_) {
return AlertDialog(
// dialog 的内容
content: Text(editController.text),
// actions 设置 dialog 的按钮
actions: [
FlatButton(
child: Text('OK'),
// 用户点击按钮后,关闭弹框
onPressed: () => Navigator.pop(context),
)
],
);
}
);
}
)
七、Container、Padding 、Center
Flutter的设计思想就是完全的widget化!连最基本的padding,Center都是widget。Container类似于android中的ViewGroup。
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(8.0),
child: Text('text'),
);
}
}
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8.0),
margin: EdgeInsets.all(4.0),
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
// 背景色
color: Colors.grey,
// 圆角
borderRadius: BorderRadius.circular(5.0),
),
// 把文本放在 Container 的中间
child: Center(
child: Text('text'),
),
);
}
}
八、水平布局Row、竖直布局Column
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
// 只有一个子元素的 widget,一般使用 child 参数来设置;Row 可以包含多个子控件,
// 对应的则是 children
children: [
Text('text1'),
Text('text2'),
Text('text3'),
],
);
}
}
Column 的使用和Row是一样的
九、Expand 控件
见上面TextField 的例子。通过使用 Expand,TextField 才能够占满一行里除按钮外的所有空间。当一行/列里有多个 Expand 时,我们还可以通过设置它的 flex 参数,在多个 Expand 之间按比例划分可用空间。
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
// 占一行的 2/3
flex: 2,
child: RaisedButton(child: Text('btn1'),),
),
Expanded(
// 占一行的 1/3
flex: 1,
child: RaisedButton(child: Text('btn2'),),
),
],
);
}
}
Expanded 只能包含一个子元素,使用的参数名是 child
十、Stack 布局
有些时候,我们可能会希望一个控件叠在另一个控件的上面。于是,Stack 应运而生:
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(
children: [
Text('foobar'),
Text('barfoo'),
],
);
}
}
默认情况下,子控件都按 Stack 的左上角对齐,于是,上面的两个文本完全一上一下堆叠在一起。我们还可以通过设置 alignment 参数来改变这个对齐的位置:
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(
// Aligment 的取值范围为 [-1, 1],Stack 中心为 (0, 0),
// 这里设置为 (-0.5, -0.5) 后,可以让文本对齐到 Container 的 1/4 处
alignment: const Alignment(-0.5, -0.5),
children: [
Container(
width: 200.0,
height: 200.0,
color: Colors.blue,
),
Text('foobar'),
],
);
}
}
实际使用中Stack中的子Widgets分为两种:
new Container(
color: Colors.yellow,
height: 150.0,
width: 500.0,
child: new Stack(children: [
new Container(
color: Colors.blueAccent,
height: 50.0,
width: 100.0,
alignment: Alignment.center,
child: Text('unPositioned'),
),
new Positioned(
left: 40.0,
top: 80.0,
child: new Container(
color: Colors.pink,
height: 50.0,
width: 95.0,
alignment: Alignment.center,
child: Text('Positioned'),
)),
]))
通过组合 Row/Column 和 Stack,已经能够完成绝大部分的布局了,所以 Flutter 里没有相对布局之类的东西。
十一、Visibility
在Flutter中,组件中没有visibility属性。visibility的控制还是比较麻烦的。目前有几种方法
1、删除法:
2、Offstage的offstage属性设置为true
@override
Widget build(BuildContext context) {
return new Offstage(
offstage: !isVisible,
child:child);
}
3、透明度
设置widget的透明度,使之不可见。但依然会绘制,浪费计算资源,且占据的位置是存在的
十二、state 生命周期
本篇文章大部分内容摘自:https://juejin.im/post/5bd54b7be51d456c430e35f6, https://juejin.im/post/5b8ce76f51882542c0626887 感谢!