面试官面试技巧和话术,Flutter学习之布局,flutter开发
代码真的是重质不重量,质量高的代码,是当前代码界提倡的,当然写出高质量的代码肯定需要一个相当高的专业素养,这需要在日常的代码书写中逐渐去吸收掌握,谁不是每天都在学习呀,目的还不是为了一个,为实现某个功能写出高质量的代码。所以,长征路还长,大家还是好好地做个务实的程序员吧。最后,小编这里有一系列Android提升学习资料,有兴趣的小伙伴们可以来看下哦~本文已被CODING开源项目:《Android学
return Padding(
child:w,
padding:EdgeInsets.fromLTRB(l ?? 0,t ?? 0,r ?? 0,b ?? 0),
);
}
1.2.实现第一行
因为上面分析,整体是用Column来实现,下面实现第一行Java synchronized原理总结
Widget ColumnWidget = Column(
//主轴上设置居中
mainAxisAlignment: MainAxisAlignment.center,
//交叉轴(水平方向)设置从左开始
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//第一行
getPaddingfromLTRB(Text(‘Java synchronized原理总结’,
style: getTextStyle(Colors.black, 16,true),
),t:0.0),
],
);
1.3.实现第二行
1.3.1实现渐变圆角Text
第二行可以看到多线程和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,
),
);
}
1.3.2.整合第二行
//第二行
Widget rowWidget = Row(
//主轴左边对齐
mainAxisAlignment: MainAxisAlignment.start,
//交叉轴(竖直方向)居中
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(“分类:”,
style: getTextStyle(Colors.blue,14,true),
),
getText(“多线程”, l1),
getText(“Java深入”, l2),
],
);
//根Widget
Widget ColumnWidget = Column(
//主轴上设置居中
mainAxisAlignment: MainAxisAlignment.center,
//交叉轴(水平方向)设置从左开始
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//第一行
getPaddingfromLTRB(Text(‘Java synchronized原理总结’,
style: getTextStyle(Colors.black, 16,true),
),t:0.0),
//第二行
getPaddingfromLTRB(rowWidget,t:10.0),
],
);
1.4.实现第三行
第三行就简单了,直接一个RowWidget,内部嵌套Expanded、Text、Icon就Ok了,代码如下:
//第三行
Widget rowthreeWidget = Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
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)
],
);
1.5.整体
//根Widget
Widget ColumnWidget = Column(
//主轴上设置居中
mainAxisAlignment: MainAxisAlignment.center,
//交叉轴(水平方向)设置从左开始
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//第一行
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,
)
),
),
);
最终效果如下:

2.布局二
直接上电影卡片布局,如下:

大致把图看了一遍,大致框架是最外层是用Row,左孩子是图片,右孩子是Column,其孩子分为五行,最后一行主演还是用Row来实现,上分析图:

2.1.实现右边图片
//根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: [
LayoutTwoLeft,
],
);
2.2.实现圆形头像
就是用自带的CircleAvatar这个Widget来实现:
//右下角圆形
CircleAvatar getCircleAvator(String image_url){
//圆形头像
return CircleAvatar(
backgroundColor: Colors.white,
backgroundImage: NetworkImage(image_url),
);
}
2.3.实现右边布局
右布局就是用一个Column来实现,一列一列往下实现即可:
//右布局
Widget LayoutTwoRightColumn = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//电影名称
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: [
Text(‘主演:’),
//以Row从左到右排列头像
Row(
children: [
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,
),
);
右布局用Expanded就是为了占满剩余空间。
2.4.整合
//整体
Widget RowWidget = Row(
//主轴上设置从开始方向对齐
mainAxisAlignment: MainAxisAlignment.start,
//交叉轴(水平方向)居中
crossAxisAlignment: CrossAxisAlignment.center,
children: [
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.布局三
同样直接上需求:

一看还是根布局直接用Column,一行一行实现就可以了,这个布局稍微简单一点,上分析图:

3.1.实现第一行
//布局三开始第一行
Widget LayoutThreeOne = Row(
children: [
Expanded(
child: Row(
children: [
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),
],
);
3.2.实现第三行
//布局三开始第三行
Widget LayoutThreeThree = Row(
children: [
Expanded(
child: Row(
children: [
Text(‘分类:’),
getPaddingfromLTRB(Text(‘开发环境/Android’,
style:getTextStyle(Colors.deepPurpleAccent, 14, false)),l:8.0),
],
),
),
Text(‘发布时间:2018-12-13’),
],
);
3.3.整合
//布局三整合
Widget LayoutThreeColumn = Column(
//主轴上设置居中
mainAxisAlignment: MainAxisAlignment.center,
//交叉轴(水平方向)设置从左开始
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//第一行
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,
)
),
),
);
}
运行效果:

4.添加ListView
上面实现了基本的布局,有了item后,那必须有ListView,这里简单模拟一下实现一下:
return new Scaffold(
appBar: new AppBar(
title: new Text(‘Flutter Demo’),
),
//ListView提供一个builder属性
body: ListView.builder(
//数目
itemCount: 20,
//itemBuilder是一个匿名回调函数,有两个参数,BuildContext 和迭代器index
//和ListView的Item项类似 迭代器从0开始 每调用一次这个函数,迭代器就会加1
itemBuilder: (BuildContext context,int index){
return Column(
children: [
cardWidget,
],
);
}),
);
发现屏幕上被20条Item项填充满,这里想想,把下拉刷新和上滑加载加上,Flutter肯定会有方法的。
4.1.下拉刷新
在Flutter已经提供和原生Android一样的刷新组件,叫做RefreshIndicator,是MD风格的,Flutter里面的ScrollView和子Widget都可以添加下拉刷新,只要在子``Widget的上层包裹一层RefreshIndicator`,先看看构造方法:
const RefreshIndicator({
Key key,
@required this.child,
this.displacement = 40.0,//下拉刷新的距离
@required this.onRefresh,//下拉刷新回调方法
this.color, //进度指示器前景色 默认是系统主题色
this.backgroundColor, //背景色
this.notificationPredicate = defaultScrollNotificationPredicate,
this.semanticsLabel, //小部件的标签
this.semanticsValue, //加载进度
})
包裹住ListView,并且定义下拉刷新方法:
return new Scaffold(
appBar: new AppBar(
title: new Text(‘Flutter Demo’),
),
body: RefreshIndicator(
//ListView提供一个builder属性
child: ListView.builder(
//数目
itemCount: 20,
//itemBuilder是一个匿名回调函数,有两个参数,BuildContext 和迭代器index
//和ListView的Item项类似 迭代器从0开始 每调用一次这个函数,迭代器就会加1
itemBuilder: (BuildContext context,int index){
return Column(
children: [
cardWidget,
],
);
}),
onRefresh: _onRefresh,),
);
//下拉刷新方法
Future _onRefresh() async {
//写逻辑
}
可以看到上面定义刷新方法_onRefresh,这里先不加任何逻辑。把根Widget继承StatefulWidget,因为后面涉及到状态更新:
class HomeStateful extends StatefulWidget{
@override
State createState(){
return new HomeWidget();
}
}
class HomeWidget extends State {
//列表要显示的数据
List list = new List();
//是否正在加载 刷新
bool isfresh = false;
//这个方法只会调用一次,在这个Widget被创建之后,必须调用super.initState()
@override
void initState(){
super.initState();
//初始化数据
initData();
}
//延迟3秒后刷新
Future initData() async{
await Future.delayed(Duration(seconds: 3),(){
setState(() {
//用生成器给所有元素赋初始值
list = List.generate(20, (i){
return i;
});
});
});
}
}
一开始先创建并初始化长度是20的List集合,ListView根据这个集合长度来构建对应数目的Item项,上面代码是初始化3秒后才刷新数据,并加了标记isfresh是否加载刷新,Scafford代码如下:
//ListView Item
Widget _itemColumn(BuildContext context,int index){
if(index <list.length){
return Column(
children: [
cardWidget,
],
);
}
}
return new Scaffold(
appBar: new AppBar(
title: new Text(‘Flutter Demo’),
),
body: RefreshIndicator(
//ListView提供一个builder属性
child: ListView.builder(
//集合数目
itemCount: list.length,
//itemBuilder是一个匿名回调函数,有两个参数,BuildContext 和迭代器index
//和ListView的Item项类似 迭代器从0开始 每调用一次这个函数,迭代器就会加1
itemBuilder: _itemColumn,
),
onRefresh: _onRefresh,),
);
}
下面把下拉刷新方法逻辑简单加一下,我这边只是重新将集合清空,然后重新添加8条数据,只是为了看刷新效果而儿:
//下拉刷新方法
Future _onRefresh() async {
//写逻辑 延迟3秒后执行刷新
//刷新把isfresh改为true
isfresh = true;
await Future.delayed(Duration(seconds: 3),(){
setState(() {
//数据清空再重新添加8条数据
list.clear();
list.addAll(List.generate(8, (i){
return i;
}));
});
});
}
为了看到刷新效果,当刷新的时候,因为isfresh为true,收藏图标♥️改为红色,否则是黑色:
//布局三开始第一行
Widget LayoutThreeOne = Row(
children: [
Expanded(
child: Row(
children: [
Text(‘作者:’),
Text(‘HuYounger’,
style: getTextStyle(Colors.redAccent[400], 14, false),
),
],
)
),
//收藏图标 改为以下
getPaddingfromLTRB(Icon(Icons.favorite,color:isfresh ? Colors.red : Colors.black),r:10.0),
//分享图标
Icon(Icons.share,color:Colors.black),
],
);
效果如下:

4.2.上拉加载
在Flutter中加载更多的组件没有是提供的,那就要自己来实现,我的思路是,当监听滑到底部时,到底底部就要做加载处理。而ListView有ScrollController这个属性来控制ListView的滑动事件,在initState添加监听是否到达底部,并且添加上拉加载更多方法:
class HomeWidget extends State {
//ListView控制器
ScrollController _controller = ScrollController();
//这个方法只会调用一次,在这个Widget被创建之后,必须调用super.initState()
@override
void initState(){
super.initState();
//初始化数据
initData();
//添加监听
_controller.addListener((){
//这里判断滑到底部第一个条件就可以了,加上不在刷新和不是上滑加载
if(_controller.position.pixels == _controller.position.maxScrollExtent){
//滑到底部了
_onGetMoreData();
}
});
}
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。






既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
最后
代码真的是重质不重量,质量高的代码,是当前代码界提倡的,当然写出高质量的代码肯定需要一个相当高的专业素养,这需要在日常的代码书写中逐渐去吸收掌握,谁不是每天都在学习呀,目的还不是为了一个,为实现某个功能写出高质量的代码。
所以,长征路还长,大家还是好好地做个务实的程序员吧。
最后,小编这里有一系列Android提升学习资料,有兴趣的小伙伴们可以来看下哦~
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
持续更新**
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-LRnrTFN2-1712351856074)]
最后
代码真的是重质不重量,质量高的代码,是当前代码界提倡的,当然写出高质量的代码肯定需要一个相当高的专业素养,这需要在日常的代码书写中逐渐去吸收掌握,谁不是每天都在学习呀,目的还不是为了一个,为实现某个功能写出高质量的代码。
所以,长征路还长,大家还是好好地做个务实的程序员吧。
最后,小编这里有一系列Android提升学习资料,有兴趣的小伙伴们可以来看下哦~
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
更多推荐



所有评论(0)