- Widget树是我们创建UI的方式,在Flutter中我们经常看到或听到这样一句话:一切皆Widget,Widget地狱嵌套。为了代码更容易理解:尽可能的保持Widget树层级较浅。
Material Design:Widget树的属性
Scaffold:脚手架,实现Material可视化布局
AppBar:界面顶部实现工具栏
CircleAvatar:显示一张圆形用户资料照片,可用于任何图片
Divider:绘制一条具有上下边距的水平线
SingleChildScrollView:可将垂直或水平滚动能力增加到单个子Widget上,防止屏幕溢出,内容过多时不建议使用,影响性能
Padding:可添加上、下、左、右内边距
Column:显示子Widget纵向列表
Row:显示子Widget横向列表
Container:可用于空白占位符(不可见),也可设置其它属性灵活运用
Expanded:可填充从属于Column或Row Widget的子Widget可用空间
Text:界面显示的文本
Stack:层叠组件、绝对定位
Positioned:允许设置宽高,与Stack结合使用,指定Stack Widget上、下、左、右四边的定位距离
//引入Material风格库,使用Material风格组件
import 'package:flutter/material.dart';
//创建有状态Widget
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
//创建变量,初始值0
int _counter = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Widget Tree'),
),
body: SafeArea(//SafeArea适配屏幕安全区
child: SingleChildScrollView(//防止Widget屏幕滚动溢出
child: Padding(//内边距
padding: EdgeInsets.all(16.0),//上下左右边距16
child: Column(//纵向列表,可放置多个子Widget
children: <Widget>[
const RowWidget(),//Widget
Padding(
padding: EdgeInsets.all(16.0),
),
const RowAndColumnWidget(),//Widget
CounterTextWidget(counter: _counter),//Widget
TextButton(//按扭
child: Text('Add to Counter'),
//点击事件宣染界面变化值
onPressed: () {
setState(() {
//回调方法
_addToCounter();
});
},
),
],
),
),
),
),
);
}
//自定义方法函数
void _addToCounter() {
return setState(() {
_counter++;
});
}
}
//构建自定义类Widget
class CounterTextWidget extends StatelessWidget {
//使用const关键字得到缓存性能优势
const CounterTextWidget({
Key key,
@required int counter,
}) : _counter = counter,
super(key: key);
final int _counter;
@override
Widget build(BuildContext context) {
print('CounterTextWidget $_counter');
return Text('CounterTextWidget $_counter');
}
}
//构建类Widget
class RowWidget extends StatelessWidget {
const RowWidget({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
print('RowWidget');
return Row(
children: <Widget>[
Container(
color: Colors.yellow,
height: 40.0,
width: 40.0,
),
Padding(
padding: EdgeInsets.all(16.0),
),
Expanded(
child: Container(
color: Colors.amber,
height: 40.0,
width: 40.0,
),
),
Padding(
padding: EdgeInsets.all(16.0),
),
Container(
color: Colors.brown,
height: 40.0,
width: 40.0,
),
],
);
}
}
//构建类Widget
class RowAndColumnWidget extends StatelessWidget {
const RowAndColumnWidget({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
print('RowAndColumnWidget');
return Row(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
color: Colors.yellow,
height: 60.0,
width: 60.0,
),
Padding(
padding: EdgeInsets.all(16.0),
),
Container(
color: Colors.amber,
height: 40.0,
width: 40.0,
),
Padding(
padding: EdgeInsets.all(16.0),
),
Container(
color: Colors.brown,
height: 20.0,
width: 20.0,
),
Divider(),
//调用RowAndStackWidget
const RowAndStackWidget(),
Divider(),
Text('End of the Line. Date: ${DateTime.now()}'),
],
),
],
);
}
}
//构建类Widget
class RowAndStackWidget extends StatelessWidget {
const RowAndStackWidget({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
print('RowAndStackWidget');
return Row(
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.lightGreen,
radius: 100.0,
child: Stack(
children: <Widget>[
Container(
height: 100.0,
width: 100.0,
color: Colors.yellow,
),
Container(
height: 60.0,
width: 60.0,
color: Colors.amber,
),
Container(
height: 40.0,
width: 40.0,
color: Colors.brown,
),
],
),
),
],
);
}
}
- 以上代码使用了类Widget提高代码理解可阅读性
- 除了用类构建Widget还可以用常量与方法函数构建Widget,注意在使用常量初始化时Widget会依赖父Widget的BuildContext对象,每次重绘父Widget,常量也会重绘,因此无进行性能优化,所以不推荐使用,方法函数Widget同理,下面我看一下常量widget与方法函数Widget的写法:
//常量Widget
final container = Container(
color:Colors.Blue,
height:40,
width:40);
//方法Widget
Widget _buildContainer(){
return Container(
color:Colors.Blue,
height:40,
width:40,
);
}