布局
Scaffold
的body
设置为Container
,如果Container
没有子元素,则继承父容器的大小。
import 'package:flutter/material.dart';
void main() {
runApp(MainPageWidget());
}
class MainPageWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("LayoutWidget")),
body: LayoutWidget(),
),
);
}
}
class LayoutWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
);
}
}
对于其他位置的Container,默认是没有大小的。
//green显示不了,默认是没有空间的,如果取消height则可以显示,默认横向占满全屏,继续取消width,则可以定制横向的宽度。
class LayoutWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: Row(
children: [
Container(
color: Colors.green,
// width: 20,
// height: 30,
)
],
),
);
}
}
如果Container有内容,则Container的大小为包含所有子widget的大小。
// 本来最外层的container红色部分是全屏的,但是添加内容后,只显示一部分。
class LayoutWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: Row(
children: [
Container(
color: Colors.green,
child: Icon(Icons.add),
),
Container(
color: Colors.green,
child: Icon(Icons.ad_units),
),
Container(
color: Colors.green,
child: Icon(Icons.ac_unit_outlined),
)
],
),
);
}
}
padding设置内边距,内边距部分还是当前widget所占用的空间。下面加号的位置上下左右各添加了30,因此父容器Contaienr的大小也会变大。
class LayoutWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: Row(
children: [
Container(
color: Colors.green,
padding: EdgeInsets.all(30),
child: Icon(Icons.add),
),
Container(
color: Colors.green,
child: Icon(Icons.ad_units),
),
Container(
color: Colors.green,
child: Icon(Icons.ac_unit_outlined),
)
],
),
);
}
}
margin设置外边距,当前widget离其他widget保持的距离。
// 第一个container添加一个margin
Container(
color: Colors.green,
padding: EdgeInsets.all(30),
margin: EdgeInsets.all(20),
child: Icon(Icons.add),
),
此时可以看到绿色部分外面还有20的红色部分。
当限制高度的时候,会导致widget显示不全,此时对于容器大小不变,只是内容会按照原来的大小显示子widget,但是当前widget由于设置了margin,当前widget会满足margin的要求,因此会被截断。
Container(
color: Colors.green,
padding: EdgeInsets.all(30),
margin: EdgeInsets.all(20),
child: Icon(Icons.add),
height: 10,
),
同样,限制高度的时候,也有可能会超过当前widget的需要大小,此时仍然优先满足margin,其次才是满足padding,意味着padding的显示未必是设置的值。
Container(
color: Colors.green,
padding: EdgeInsets.all(30),
margin: EdgeInsets.all(20),
child: Icon(Icons.add),
height: 200,
),
Container的对齐方式
- Row
- Column
- Stack
默认Row的方式是横着显示在左上角,是因为当前默认的对齐是左上角。我们可以通过aligenment进行设置。屏幕的中心点为(0,0).而默认的值为(-1,-1)。
当我们设置child:Row的时候,表示横着布局,此时设置X轴就无效了,同样,如果设置child:Column,则设置Y轴就无效了。
return Container(
color: Colors.red,
// alignment: Alignment(-1,-1),
child: Row(
children: [
Container(
color: Colors.green,
child: Icon(Icons.add),
),
Container(
color: Colors.blue,
child: Icon(Icons.ad_units),
),
Container(
color: Colors.purple,
child: Icon(Icons.ac_unit_outlined),
)
],
),
);
mainAxisAlignment 主轴对齐方式
当内容只有一个的情况比较特殊,spaceBetween则显示在左边,spaceAround和spaceEvenly显示在中间。
enum MainAxisAlignment {
/// Place the children as close to the start of the main axis as possible.
///
/// If this value is used in a horizontal direction, a [TextDirection] must be
/// available to determine if the start is the left or the right.
///
/// If this value is used in a vertical direction, a [VerticalDirection] must be
/// available to determine if the start is the top or the bottom.
start,//开始的位置,默认值
/// Place the children as close to the end of the main axis as possible.
///
/// If this value is used in a horizontal direction, a [TextDirection] must be
/// available to determine if the end is the left or the right.
///
/// If this value is used in a vertical direction, a [VerticalDirection] must be
/// available to determine if the end is the top or the bottom.
end,// 结束的位置
/// Place the children as close to the middle of the main axis as possible.
center,//居中
/// Place the free space evenly between the children.
spaceBetween,// 两边没有间距,中间的平分
/// Place the free space evenly between the children as well as half of that
/// space before and after the first and last child.
spaceAround,// 两边的间距是中间的间距的一般
/// Place the free space evenly between the children as well as before and
/// after the first and last child.
spaceEvenly,//两边的间距等于中间的间距
}
crossAxisAlignment 交叉轴的对齐方式。
return Container(
color: Colors.red,
alignment: Alignment(1,0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.green,
child: Icon(Icons.add,size: 30,),
),
Container(
color: Colors.blue,
child: Icon(Icons.ad_units,size: 20,),
),
Container(
color: Colors.purple,
child: Icon(Icons.ac_unit_outlined,size: 10,),
)
],
),
);
Expanded 扩展以填充屏幕
当只有一个的时候,则会拉升这个widget,如果有多个Expanded,则会这些Expanded平分。
return Container(
color: Colors.red,
alignment: Alignment(1,0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: Container(
color: Colors.green,
child: Icon(Icons.add,size: 30,),
)),
Container(
color: Colors.blue,
child: Icon(Icons.ad_units,size: 20,),
),
Container(
color: Colors.purple,
child: Icon(Icons.ac_unit_outlined,size: 10,),
)
],
),
);
逆序
默认widget是从左到右显示,但是Row里面如果设置了阅读方向从右边到左边,则可以让Widget逆序。
void main() {
runApp(MainPageWidget());
}
class MainPageWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("LayoutWidget")),
body: ReverseWidget(),
),
);
}
}
class ReverseWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: Row(
textDirection: TextDirection.rtl,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("第一个",style: TextStyle(backgroundColor: Colors.green)),
Text("第二个",style: TextStyle(backgroundColor: Colors.blue))
],
),
);
}
}
绝对定位
import 'package:flutter/material.dart';
void main() {
runApp(MainPageWidget());
}
class MainPageWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("LayoutWidget")),
body: PositionWidget(),
),
);
}
}
class PositionWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: Stack(
children: [
Positioned(child: Text("第一个",style: TextStyle(backgroundColor: Colors.green,fontSize: 50))),
Positioned(child: Text("第二个",style: TextStyle(backgroundColor: Colors.blue))),
// right=10表示右对齐
Positioned(child: Text("第二个",style: TextStyle(backgroundColor: Colors.blue)),right: 10,top: 20,),
],
),
);
}
}
宽高比
当设置了宽度和高度的其中一个的时候才有效,如果两个都设置了则无效。
void main() {
runApp(MainPageWidget());
}
class MainPageWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("LayoutWidget")),
body: RatioWidget(),
),
);
}
}
class RatioWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
// 如果不设置这个,则当前Widget会和子widget大小一致
alignment: Alignment(0,0),
child: Container(
color: Colors.blue,
width: 300,
// 宽高比1/2 ,设置了宽度300,则高度为600
child: AspectRatio(aspectRatio: 1/2,),
),
);
}
}