布局
若想将文字置于当前页面的中心方位,能够运用Center
或许Alignment
控件
Center
class LayoutDemo extends StatelessWidget {
const LayoutDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Center(
child: Text('LayoutDemo', style:TextStyle(fontSize: 20, color: Colors.red, backgroundColor: Colors.cyan))
);
}
}
Alignment
运用Container
包装一层,设置子控件的成员变量Alignment
class LayoutDemo extends StatelessWidget {
const LayoutDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.orange,
alignment: const Alignment(0, 0),
child: const Text('LayoutDemo', style:TextStyle(fontSize: 20, backgroundColor: Colors.cyan))
);
}
}
经过调试Alignment(x, y)
可知坐标系如下图,原点位于中心方位,x
、y
的取值范围均为[-1,1]
布局
Flutter
中的布局与前端中的布局方式很类似,都是FlexBox
形式,下面别离介绍横向布局
、纵向布局
、层级布局
Row(横向布局)
运用Row(横向布局)
布局的控件会在横轴方向占满父部件
留意这个特点mainAxisAlignment(主轴方向布局)
共有以下几个选项:
-
start
:布局从主轴开端的方位正向布局 -
end
:布局从主轴完毕的方位开端反向布局 -
center
:布局位于主轴中心的方位 -
spaceBetween
:把主轴方向剩余的空间均匀的散布于控件之间 -
spaceAround
:把主轴方向剩余的空间平均分配到空间周围 -
spaceEvenly
:把主轴发现剩余的空间平均分配在控件周围空余的部分
class LayoutDemo extends StatelessWidget {
const LayoutDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.orange,
alignment: const Alignment(0, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
color: Colors.red,
width: 50,
height: 50,
child: cosnt Icon(Icons.add),
),
Container(
color: Colors.blue,
width: 50,
height: 50,
child: cosnt Icon(Icons.search),
),
Container(
color: Colors.white,
width: 50,
height: 50,
child: cosnt Icon(Icons.battery_alert),
),
],
)
);
}
}
mainAxisAlignment
start
布局沿主轴开端的方向,刚才现已论述过这儿的坐标系,又是Row
摆放,则主轴是x
方向,从左至右
end
布局沿主轴完毕的方向,所以是从右至左来排布
center
布局位于主轴中心的方位
spaceBetween
把主轴方向剩余的空间均匀的散布于控件之间
spaceAround
把主轴方向剩余的空间平均分配到空间周围
spaceEvenly
把主轴发现剩余的空间平均分配在控件周围空余的部分
crossAxisAlignment
这儿举例仍然是在Row(横向布局)
的状况下来讨论crossAxisAlignment
特点
crossAxisAlignment
中有以下几个选项:
-
start
:向穿插轴开端的方向对齐 -
end
:向穿插轴完毕的方向对齐 -
center
:穿插轴方向居中对齐 -
stretch
:填满穿插轴方向 -
baseline
:文字基线对齐
class LayoutDemo extends StatelessWidget {
const LayoutDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.orange,
alignment: const Alignment(0, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
child: const Icon(Icons.add, size: 50),
),
Container(
color: Colors.blue,
child: const Icon(Icons.search, size: 100),
),
Container(
color: Colors.white,
child: const Icon(Icons.battery_alert, size: 150),
),
],
)
);
}
}
start
在穿插轴方向从上到下进行布局,相当于顶部对齐
end
在穿插轴方向从下到上进行布局,相当于底部对齐
center
在穿插轴方向上居中布局,这也是默许特点
stretch
子控件将撑满穿插轴方向
baseline
baseline
要配合文字来进行演示,一起也需求设置textBaseline
,意思就是以文字的基线来进行对齐
class LayoutDemo extends StatelessWidget {
const LayoutDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.orange,
alignment: const Alignment(0, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Container(
height: 80,
color: Colors.red,
child: const Text('好好学习', style: TextStyle(fontSize: 15))
),
Container(
height: 80,
color: Colors.blue,
child: const Text('天天要吃饭', style: TextStyle(fontSize: 30))
),
Container(
height: 80,
color: Colors.white,
child: const Text('晚上', style: TextStyle(fontSize: 60))
),
],
)
);
}
}
Expanded(填充布局)
Expanded(填充布局)
:
- 在主轴方向不会剩余间隙,将被
Expanded
包装的部件进行拉伸和紧缩 - 主轴横向,设置宽度没有意义
- 主轴纵向,设置高度没有意义
- 当
Text
被Expanded
包装后文字能够自动换行,所以Expanded
也被称为灵活布局
class LayoutDemo extends StatelessWidget {
const LayoutDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// return const Center(
// child: Text('LayoutDemo', style:TextStyle(fontSize: 20, color: Colors.red, backgroundColor: Colors.cyan))
// );
return Container(
color: Colors.orange,
alignment: const Alignment(0, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Expanded(child: Container(
height: 80,
color: Colors.red,
child: const Text('好好学习', style: TextStyle(fontSize: 15))
)),
Expanded(child: Container(
height: 80,
color: Colors.blue,
child: const Text('天天要吃饭', style: TextStyle(fontSize: 30))
)),
Expanded(child: Container(
height: 80,
color: Colors.white,
child: const Text('晚上', style: TextStyle(fontSize: 60))
))
],
)
//child: const Text('LayoutDemo', style:TextStyle(fontSize: 20, backgroundColor: Colors.cyan))
);
}
}
Column(纵向布局)
和Row
相同,运用Column(纵向布局)
布局的控件会在纵轴方向占满父部件,mainAxisAlignment
和crossAxisAlignment
特点同上,这儿不再演示
class LayoutDemo extends StatelessWidget {
const LayoutDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.orange,
alignment: const Alignment(0, 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
// textBaseline: TextBaseline.alphabetic,
children: [
Expanded(child: Container(
height: 80,
color: Colors.red,
child: const Text('好好学习', style: TextStyle(fontSize: 15))
)),
Expanded(child: Container(
height: 80,
color: Colors.blue,
child: const Text('天天要吃饭', style: TextStyle(fontSize: 30))
)),
Expanded(child: Container(
height: 80,
color: Colors.white,
child: const Text('晚上', style: TextStyle(fontSize: 60))
))
],
)
);
}
}
Stack(层次布局)
class StackDemo extends StatelessWidget {
const StackDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
alignment: const Alignment(-1,-1),
children: [
Container(
color: Colors.white,
width: 200,
height: 200,
child: const Icon(Icons.add)
),
Container(
color: Colors.blue,
width: 100,
height: 100,
child: const Icon(Icons.search)
),Container(
color: Colors.cyan,
width: 50,
height: 50,
child: const Icon(Icons.alarm)
),
],
);
}
}
Stack
也叫层次布局,如果这儿需求子控件一个在左一个在右的话则需求运用到Stack
中的Positioned
特点来完结控制子控件的相对方位
class StackDemo extends StatelessWidget {
const StackDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
alignment: const Alignment(-1,-1),
children: [
Positioned(child: Container(
color: Colors.white,
width: 200,
height: 200,
child: const Icon(Icons.add)
)),
Positioned(
left: 1,
bottom: 1,
child: Container(
color: Colors.blue,
width: 100,
height: 100,
child: const Icon(Icons.search)
)),
Positioned(
right: 1,
child: Container(
color: Colors.cyan,
width: 50,
height: 50,
child: const Icon(Icons.alarm)
))
],
);
}
}
AspectRatio(设置宽高比)
class AspectRatioDemo extends StatelessWidget {
const AspectRatioDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
//padding: const EdgeInsets.all(10),
color: Colors.blue,
//width: 400,
height: 150,
child: AspectRatio(
aspectRatio: 2/1,
child: Container(
alignment: const Alignment(0,0),
color: Colors.red,
),
),
);
}
}
经过设置aspectRatio(宽高比)
为2/1
来设置宽度为300
,如果父控件中设置了宽度,则以父控件为主
状况办理
现在需求是如果有数据改动了需求实时烘托到页面上以便看到改动,举例如下
class StateManageDemo extends StatelessWidget {
StateManageDemo({Key? key}) : super(key: key);
int count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('StateManageDemo', style: TextStyle(fontSize: 15),)),
body: Center(
child: Chip(
label: Text('$count'),
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: (){
count++;
debugPrint('count = $count');
},
),
);
}
}
可是运行后发现,每次点击按钮后的确现已改动了count
的值,可是并未更新到页面上,甚至热更新也不能更新成果上去。原因是StatelessWidget
是一个无状况的控件,也就是说在创立完结后就不会再进入其build
办法了,那么也就无法完结更新,所以如果想运用数据有改动的控件能够运用StatefullWidget
class StateManageDemo extends StatefulWidget {
const StateManageDemo({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _SMDState();
}
class _SMDState extends State<StateManageDemo>{
int count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('StateManageDemo', style: TextStyle(fontSize: 15),)),
body: Center(
child: Chip(
label: Text('$count'),
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: (){
count++;
setState(() {
});
debugPrint('count = $count');
},
),
);
}
}
运用StatefullWidget
控件时需求搭配运用一个状况办理的类,本来的build
办法放在这个类中实现,也就是说数据由这个类来办理和烘托,并且在状况改动后需求设置回调setState
,这样就能够完结上面的需求了。