边做边学
布局简单有:
Row:横向布局
Column:纵向布局
先做一个简单的同时包含横竖的布局
return new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Text(
"test1",
style: new TextStyle(color: Colors.blue),
),
new Text(
"test2",
style: new TextStyle(color: Colors.blue),
),
new Text(
"test3",
style: new TextStyle(color: Colors.blue),
)
],
)
],
);
其中mainAxisAlignment属性代表对齐方向,children是子内容的数组
运行的表现非常难看,就不截图了
下面给Row设置大小和背景色,没发现直接设置的方法,只好在引入一个Widget:Container
new Container(
decoration: new BoxDecoration(color: Colors.white),
child: new Row(
mainAxisSize: MainAxisSize.max,
...
),
),
只是简单的用Container包裹了一下,在Container中使用了decoration参数,加入了一个白色的背景
而大小则使用了mainAxisSize参数, MainAxisSize.max指在主方向铺满
flutter本身是沉浸式的,由于没有使用Material控件,布局直接从状态栏开始了
对于这种情况,可以直接使用Material,如果希望自定义,那么就需要使用SafeArea
return new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new SafeArea(
child: new Container(
decoration: new BoxDecoration(color: Colors.white),
child: new Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Text(
"test1",
style: new TextStyle(color: Colors.blue),
),
new Text(
"test2",
style: new TextStyle(color: Colors.blue),
),
new Text(
"test3",
style: new TextStyle(color: Colors.blue),
)
],
),
),
),
],
);
使用SafeArea包裹Container后,显示就正常了,同时对于刘海屏等影响也同样生效
效果如下:
然后我们把Row当做标题栏,做一些优化
return new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new SafeArea(
child: new Container(
decoration: new BoxDecoration(color: Colors.white),
height: 50,
padding: EdgeInsets.fromLTRB(20, 0, 20, 0 ),
child: new Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Text(
"back",
style: new TextStyle(
decoration: TextDecoration.none,
fontSize: 18,
color: Colors.blue),
),
new Expanded(
flex: 1,
child: new Text(
"Title",
textAlign: TextAlign.center,
style: new TextStyle(
decoration: TextDecoration.none,
fontSize: 26,
color: Colors.blue),
),
),
new Text(
"more",
style: new TextStyle(
decoration: TextDecoration.none,
fontSize: 18,
color: Colors.blue),
)
],
),
),
),
],
);
其中TextStyle加入了decoration: TextDecoration.none属性用于去掉下划线,并增加了文字大小设置,另外在Container加入了height和padding
这里使用Expanded,作用类似layout_weight,可以实现按比例布局
而后例如我们要在下面布局的中加入一个居中的文字,只需在Column中加入:
new Expanded(
flex: 1,
child: new Center(
child: new Text(
"Body",
textAlign: TextAlign.center,
style: new TextStyle(
decoration: TextDecoration.none,
fontSize: 26,
color: Colors.white),
),
),
)
显示如图:
这里除了使用Expanded外其它均不能完成全屏效果,Center只是个辅助的定位Widget,因为在flutter的理念中万物皆Widget,定位也是Widget。
下一步比较简单,我们把内容部分分成两块,左边显示头像、姓名、简介:
new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
/*头像姓名区*/
new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Container(
width: 100,
height: 100,
margin: EdgeInsets.fromLTRB(30, 30, 0, 30),
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
image: AssetImage('images/photo.jpeg'),
),
),
),
new Container(
margin: EdgeInsets.fromLTRB(30, 0, 0, 0),
child: new Center(
child: new Text(
"姓名:李白",
style: new TextStyle(
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
fontSize: 26,
color: Colors.blue),
)),
),
],
),
new Expanded(
flex: 1,
child: new Container(
margin: EdgeInsets.fromLTRB(20, 10, 20, 10),
width: 350,
child: new SingleChildScrollView(
child: new Text(
"李白 (唐代著名浪漫主义诗人) 编辑 讨论99+\n\t李白(701年-762年) ,字太白,号青莲居士,又号“谪仙人”,是唐代伟大的浪漫主义诗人,被后人誉为“诗仙”,与杜甫并称为“李杜”,为了与另两位诗人李商隐与杜牧即“小李杜”区别,杜甫与李白又合称“大李杜”。据《新唐书》记载,李白为兴圣皇帝(凉武昭王李暠)九世孙,与李唐诸王同宗。其人爽朗大方,爱饮酒作诗,喜交友。\n\t李白深受黄老列庄思想影响,有《李太白集》传世,诗作中多以醉时写的,代表作有《望庐山瀑布》《行路难》《蜀道难》《将进酒》《明堂赋》《早发白帝城》等多首。\n\t李白所作词赋,宋人已有传记(如文莹《湘山野录》卷上),就其开创意义及艺术成就而言,“李白词”享有极为崇高的地位。",
textAlign: TextAlign.start,
style: new TextStyle(
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
fontSize: 20,
color: Colors.blue),
)),
alignment: Alignment.topLeft,
),
)
],
),
表现如图:
这里为了控制子控件对齐,引入了一个新的参数:crossAxisAlignment
mainAxisAlignment与crossAxisAlignment的区别就是控制方向不同,mainAxisAlignment控制主方向的对齐,crossAxisAlignment控制副方向
其中Row为横向,主方向就是水平方向,副方向就是竖直方向,这样来分
除此之外,由于flutter文字默认加粗,使用了fontWeight参数设置为正常粗细,同时引入了margin和padding,用法和android中相同,通过上下左右四个方向的值来控制。
另外还引入了一个图片控件,这里主要讲布局,暂不详述
而在另一面,我们放入一张充满剩余空间的图片:
new Expanded(
flex: 1,
child: new Column(children: <Widget>[
new Expanded(
flex: 1,
child: new Container(
color: Colors.red,
child: new Image(
image: AssetImage("img_info_libai.jpeg"),
fit: BoxFit.cover),
))
])),
这个写法可以说很不美观,一个Expanded用于水平撑满,而后在嵌套一个竖直布局Column,为的仅是在其中使用Expanded来达到同时纵向的充满,不过试了几种方式都没能达到效果,只能暂时先这么写了。
整体图如下:
整体代码如下:
class Test extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Container(
child: new Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new SafeArea(
//标题
child: new Container(
decoration: new BoxDecoration(color: Colors.white),
height: 50,
padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
child: new Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Text(
"back",
style: new TextStyle(
decoration: TextDecoration.none,
fontSize: 18,
color: Colors.blue),
),
new Expanded(
flex: 1,
child: new Text(
"Title",
textAlign: TextAlign.center,
style: new TextStyle(
decoration: TextDecoration.none,
fontSize: 26,
color: Colors.blue),
),
),
new Text(
"more",
style: new TextStyle(
decoration: TextDecoration.none,
fontSize: 18,
color: Colors.blue),
)
],
),
),
),
/*内容*/
new Expanded(
flex: 1,
child: new Container(
decoration:
new BoxDecoration(color: Color(int.parse("0xffe5e5e5"))),
child: new Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
/*左侧标签*/
new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
/*头像姓名区*/
new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Container(
width: 100,
height: 100,
margin: EdgeInsets.fromLTRB(30, 30, 0, 30),
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
image: AssetImage('images/photo.jpeg'),
),
),
),
new Container(
margin: EdgeInsets.fromLTRB(30, 0, 0, 0),
child: new Center(
child: new Text(
"姓名:李白",
style: new TextStyle(
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
fontSize: 26,
color: Colors.blue),
)),
),
],
),
new Expanded(
flex: 1,
child: new Container(
margin: EdgeInsets.fromLTRB(20, 10, 20, 10),
width: 350,
child: new SingleChildScrollView(
child: new Text(
"李白 (唐代著名浪漫主义诗人) 编辑 讨论99+\n\t李白(701年-762年) ,字太白,号青莲居士,又号“谪仙人”,是唐代伟大的浪漫主义诗人,被后人誉为“诗仙”,与杜甫并称为“李杜”,为了与另两位诗人李商隐与杜牧即“小李杜”区别,杜甫与李白又合称“大李杜”。据《新唐书》记载,李白为兴圣皇帝(凉武昭王李暠)九世孙,与李唐诸王同宗。其人爽朗大方,爱饮酒作诗,喜交友。\n\t李白深受黄老列庄思想影响,有《李太白集》传世,诗作中多以醉时写的,代表作有《望庐山瀑布》《行路难》《蜀道难》《将进酒》《明堂赋》《早发白帝城》等多首。\n\t李白所作词赋,宋人已有传记(如文莹《湘山野录》卷上),就其开创意义及艺术成就而言,“李白词”享有极为崇高的地位。",
textAlign: TextAlign.start,
style: new TextStyle(
decoration: TextDecoration.none,
fontWeight: FontWeight.normal,
fontSize: 20,
color: Colors.blue),
)),
alignment: Alignment.topLeft,
),
)
],
),
new Expanded(
flex: 1,
child: new Column(children: <Widget>[
new Expanded(
flex: 1,
child: new Container(
color: Colors.red,
child: new Image(
image: AssetImage("img_info_libai.jpeg"),
fit: BoxFit.cover),
))
])),
],
)))
],
));
}
}
最后再尝试一个新的布局:Stack
new Expanded(
flex: 1,
child: new Stack(
children: <Widget>[
new Column(children: <Widget>[
new Expanded(
flex: 1,
child: new Container(
child: new Image(
image:
AssetImage("img_info_libai.jpeg"),
fit: BoxFit.cover),
))
]),
new Align(
alignment: FractionalOffset.bottomRight,
child: new Container(
height: 100,
width: 100,
child: new Image(
image: AssetImage("img_info_libai.jpeg"),
fit: BoxFit.cover),
),
)
],
))
效果如下:
可以简单认为 LinearLayout = Row/Column, FrameLayout/RelativeLayout = Stack
至此,常见的布局就已经全部ok了
欢迎纠错与交流