- 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上、下、左、右四边的定位距离
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Widget Tree'),
),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
const RowWidget(),
Padding(
padding: EdgeInsets.all(16.0),
),
const RowAndColumnWidget(),
CounterTextWidget(counter: _counter),
TextButton(
child: Text('Add to Counter'),
onPressed: () {
setState(() {
_addToCounter();
});
},
),
],
),
),
),
),
);
}
void _addToCounter() {
return setState(() {
_counter++;
});
}
}
class CounterTextWidget extends StatelessWidget {
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');
}
}
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,
),
],
);
}
}
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(),
const RowAndStackWidget(),
Divider(),
Text('End of the Line. Date: ${DateTime.now()}'),
],
),
],
);
}
}
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的写法:
final container = Container(
conlor:Colors.Blue,
height:40,
width:40);
Widget _buildContainer(){
return Container(
color:Colors.Blue,
height:40,
width:40,
);
}