Flutter -- 实例案例二:加深布局的熟练度
Posted Kevin-Dev
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter -- 实例案例二:加深布局的熟练度相关的知识,希望对你有一定的参考价值。
文章目录
前言
因为我是从事 android 开发,学习了 Flutter 之后,发现其布局和在 Android 下布局是不一样的,Android 布局是在 XML
文件下,直观性强一点,基本是整体到局部,首先是确定根布局是用 LinearLayout
还是 RelativeLayout
或者是 ConstraintLayout
等。而在 Flutter 下,都是由 Widget 来拼接起来,很多时候都是 Row+Column
合成,我自己是在草稿上画出用什么 Widget
来拼出需求布局,然后才去实现。
布局一
1. 需求
很容易看出三块竖直排列,根 Widget 用 Column 来实现,局部第一行是 Text,第二行是 Row 行,但是 Row 并不是都是统一样式,多线程和 Java 深入是带圆角背景的,下面再仔细讲解,第三行是两个文本(作者文本和时间文本),一个图标,第一个文本很容易想到 Expanded,当s时间文本和图标摆放后,其会占满剩余主轴空间。
2. 代码
- 封装 TextStyle 和 Padding
首先我看到整个布局下字体的颜色至少四种,有加粗和不加粗的,并且有部分加了padding,还是封装TextStyle和padding:
/**
* TextStyle:封装
* colors:颜色
* fontsizes:字体大小
* isFontWeight:是否加粗
*/
TextStyle getTextStyle(Color colors,double fontsizes,bool isFontWeight)
return TextStyle(
color:colors,
fontSize: fontsizes,
fontWeight: isFontWeight == true ? FontWeight.bold : FontWeight.normal ,
);
/**
* 组件加上下左右padding
* w:所要加padding的组件
* all:加多少padding
*/
Widget getPadding(Widget w,double all)
return Padding(
child:w,
padding:EdgeInsets.all(all),
);
/**
* 组件选择性加padding
* 这里用了位置可选命名参数param1,param2,...来命名参数,也调用的时候可以不传
*
*/
Widget getPaddingfromLTRB(Widget w,double l,double t,double,r,double b)
return Padding(
child:w,
padding:EdgeInsets.fromLTRB(l ?? 0,t ?? 0,r ?? 0,b ?? 0),
);
- 实现第一行
因为上面分析,整体是用Column来实现,下面实现第一行Java synchronized原理总结
Widget ColumnWidget = Column(
//主轴上设置居中
mainAxisAlignment: MainAxisAlignment.center,
//交叉轴(水平方向)设置从左开始
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//第一行
getPaddingfromLTRB(Text('Java synchronized原理总结',
style: getTextStyle(Colors.black, 16,true),
),t:0.0),
],
);
- 实现第二行
第二行可以看到多线程
和Java深入
是带渐变效果的圆角,查了网上的资料发现 Container 是有设置圆角和渐变属性的:
//抽取第二行渐变text效果
Container getText(String text,LinearGradient linearGradient)
return Container(
//距离左边距离10dp
margin: const EdgeInsets.only(left: 10),
//约束 相当于直接制定了该Container的宽和高,且它的优先级要高于width和height
constraints: new BoxConstraints.expand(
width: 70.0, height: 30.0,),
//文字居中
alignment: Alignment.center,
child: new Text(
text,
style:getTextStyle(Colors.white,14,false),
),
decoration: new BoxDecoration(
color: Colors.blue,
//圆角
borderRadius: new BorderRadius.all(new Radius.circular(6.0)),
//添加渐变
gradient:linearGradient,
),
);
- 整合第二行
//第二行
Widget rowWidget = Row(
//主轴左边对齐
mainAxisAlignment: MainAxisAlignment.start,
//交叉轴(竖直方向)居中
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text("分类:",
style: getTextStyle(Colors.blue,14,true),
),
getText("多线程", l1),
getText("Java深入", l2),
],
);
//根Widget
Widget ColumnWidget = Column(
//主轴上设置居中
mainAxisAlignment: MainAxisAlignment.center,
//交叉轴(水平方向)设置从左开始
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//第一行
getPaddingfromLTRB(Text('Java synchronized原理总结',
style: getTextStyle(Colors.black, 16,true),
),t:0.0),
//第二行
getPaddingfromLTRB(rowWidget,t:10.0),
],
);
- 实现第三行
//第三行
Widget rowthreeWidget = Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Expanded(
child: Text(
"作者:EnjoyMoving",
style: getTextStyle(Colors.grey[400], 14, true),
),
),
getPaddingfromLTRB(Text(
'时间:2019-02-02',
style: getTextStyle(Colors.black, 14, true),
), r :10.0),
getPaddingfromLTRB(Icon(
Icons.favorite_border,
color:Colors.grey[400],
),r:0.0)
],
);
- 整体
//根Widget
Widget ColumnWidget = Column(
//主轴上设置居中
mainAxisAlignment: MainAxisAlignment.center,
//交叉轴(水平方向)设置从左开始
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//第一行
getPaddingfromLTRB(Text('Java synchronized原理总结',
style: getTextStyle(Colors.black, 16,true),
),t:0.0),
//第二行
getPaddingfromLTRB(rowWidget,t:10.0),
//第三行
getPaddingfromLTRB(rowthreeWidget,t:10.0),
],
);
return new Scaffold(
appBar: new AppBar(
title: new Text('Flutter Demo'),
),
//用card裹住
body: Card(
child: Container(
//高度
height: 160.0,
//颜色
color: Colors.white,
padding: EdgeInsets.all(10.0),
child: Center(
child: ColumnWidget,
)
),
),
);
3. 效果图
布局二
1. 需求
大致框架是最外层是用 Row,左孩子是图片,右孩子是 Column,其孩子分为五行,最后一行主演还是用Row来实现,上分析图:
2. 代码
- 实现右边图片
//根Widget 布局二 开始
//右边图片布局
Widget LayoutTwoLeft = Container(
//这次使用裁剪实现圆角矩形
child:ClipRRect(
//设置圆角
borderRadius: BorderRadius.circular(4.0),
child: Image.network(
'https://img3.doubanio.com//view//photo//s_ratio_poster//public//p2545472803.webp',
width: 100.0,
height: 150.0,
fit:BoxFit.fill,
),
),
);
//整体
Widget RowWidget = Row(
//主轴上设置居中
mainAxisAlignment: MainAxisAlignment.start,
//交叉轴(水平方向)设置从左开始
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
LayoutTwoLeft,
],
);
- 实现圆形头像
就是用自带的CircleAvatar这个Widget来实现:
//右下角圆形
CircleAvatar getCircleAvator(String image_url)
//圆形头像
return CircleAvatar(
backgroundColor: Colors.white,
backgroundImage: NetworkImage(image_url),
);
- 实现右边布局
右布局就是用一个Column来实现,一列一列往下实现即可:
//右布局
Widget LayoutTwoRightColumn = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//电影名称
Text(
'流浪地球',
style: getTextStyle(Colors.black, 20.0, true),
),
//豆瓣评分
Text(
'豆瓣评分:7.9',
style: getTextStyle(Colors.black54, 16.0, false),
),
//类型
Text(
'类型:科幻、太空、灾难',
style:getTextStyle(Colors.black54, 16.0, false),
),
//导演
Text(
'导演:郭帆',
style: getTextStyle(Colors.black54, 16.0, false),
),
//主演
Container(
margin: EdgeInsets.only(top:8.0),
child:Row(
children: <Widget>[
Text('主演:'),
//以Row从左到右排列头像
Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(left:2.0),
child: getCircleAvator('https://img3.doubanio.com//view//celebrity//s_ratio_celebrity//public//p1533348792.03.webp'),
),
Container(
margin: EdgeInsets.only(left:12.0),
child: getCircleAvator('https://img3.doubanio.com//view//celebrity//s_ratio_celebrity//public//p1501738155.24.webp'),
),
Container(
margin: EdgeInsets.only(left:12.0),
child: getCircleAvator('https://img3.doubanio.com//view//celebrity//s_ratio_celebrity//public//p1540619056.43.webp'),
),
],
),
],
),
),
],
);
//布局二 右布局 用Expanded占满剩余空间
Widget LayoutTwoRightExpanded = Expanded(
child:Container(
//距离左布局10
margin:EdgeInsets.only(left:10.0),
//高度
height:150.0,
child: LayoutTwoRightColumn,
),
);
- 整合
//整体
Widget RowWidget = Row(
//主轴上设置从开始方向对齐
mainAxisAlignment: MainAxisAlignment.start,
//交叉轴(水平方向)居中
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
LayoutTwoLeft,
LayoutTwoRightExpanded,
],
);
return new Scaffold(
appBar: new AppBar(
title: new Text('Flutter Demo'),
),
body: Card(
child: Container(
//alignment: Alignment(0.0, 0.0),
height: 160.0,
color: Colors.white,
padding: EdgeInsets.all(10.0),
child: Center(
// 布局一
// child: ColumnWidget,
// 布局二
child:RowWidget,
)
),
),
);
3. 效果图
布局三
1. 需求
根布局直接用 Column,一行一行实现就可以了,这个布局稍微简单一点。
2. 代码
- 实现第一行
//布局三开始第一行
Widget LayoutThreeOne = Row(
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
Text('作者:'),
Text('HuYounger',
style: getTextStyle(Colors.redAccent[400], 14, false),
),
],
)
),
//收藏图标
getPaddingfromLTRB(Icon(Icons.favorite,color:Colors.red),r:10.0),
//分享图标
Icon(Icons.share,color:Colors.black),
],
);
- 实现第三行
//布局三开始第三行
Widget LayoutThreeThree = Row(
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
Text('分类:'),
getPaddingfromLTRB(Text('开发环境/Android',
style:getTextStyle(Colors.deepPurpleAccent, 14, false)),l:8.0),
],
),
),
Text('发布时间:2018-12-13'),
],
);
- 整合
//布局三整合
Widget LayoutThreeColumn = Column(
//主轴上设置居中
mainAxisAlignment: MainAxisAlignment.center,
//交叉轴(水平方向)设置从左开始
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
//第一行
LayoutThreeOne,
//第二行
getPaddingfromLTRB(Text('Android Monitor使用介绍',
style:getTextStyle(Colors.black, 18, false),
),t:10.0),
//第三行
getPaddingfromLTRB(LayoutThreeThree,t:10.0),
],
);
return new Scaffold(
appBar: new AppBar(
title: new Text('Flutter Demo'),
),
body: Card(
child: Container(
//alignment: Alignment(0.0, 0.0),
height: 160.0,
color: Colors.white,
padding: EdgeInsets.all(10.0),
child: Center(
// 布局一
// child: ColumnWidget,
// 布局二
// child:RowWidget,
// 布局三
child:LayoutThreeColumn,
)
),
),
);
3. 效果图
布局四
1. 需求
上面实现了基本的布局,有了item后,那必须有ListView,这里简单模拟一下实现一下:
- 添加 ListView
- 下拉刷新
- 上拉加载
- ListView.separated
return new <以上是关于Flutter -- 实例案例二:加深布局的熟练度的主要内容,如果未能解决你的问题,请参考以下文章