• 样式二

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个样式的控件布局就很简单了,结构如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 样式三

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个和样式二差不多,只不过最上面多了一块.

这里需要注意的是,那个你猜这个图片是堆叠在整个大图上面的,所以需要用到Stack这个控件,其中Stack中有个属性const FractionalOffset(double dx, double dy)用于表示子控件相对于父控件的位置

  • 样式四

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这种样式稍微复杂一点,结构如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3数据抓取

用青花瓷抓取了好奇心数据.青花瓷使用教程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

简单分析一下,has_more表示是否可以加载更多,last_key用于上拉加载的时候请求用的,feeds就是每一条数据,banners就是轮播图的信息,columns就是横向滚动的ListView的相关数据,这个后面讲.接下来就做json序列化相关的了.

4.Json序列化

首先在pubspec.yaml中导入

dependencies: json_annotation: ^2.0.0 dev_dependencies: build_runner: ^1.0.0 json_serializable: ^2.0.0

创建一个model.dart文件 引入文件

import ‘package:json_annotation/json_annotation.dart’; part ‘model.g.dart’;

其中这个model.g.dart等会儿会自动生成.这里需要掌握两个知识点

1.@JsonSerializable() 这是表示告诉编译器这个类是需要生成Model类的 2,@JsonKey 由于服务器返回的部分数据名称在Dart语言中是不被允许的,比如has_more,Dart中命名不能出现下划线,所以就需要用到@JsonKey来告诉编译器这个参数对于json中的哪个字段

@JsonSerializable()
class Feed {
String image;
int type;
@JsonKey(name: ‘index_type’)
int indexType;
Post post;
@JsonKey(name: ‘news_list’)
List newsList;
Feed(this.image,this.type,this.post,this.indexType,this.newsList);
factory Feed.fromJson(Map<String,dynamic> json) => _KaTeX parse error: Expected group after '_' at position 54: …c> toJson() => _̲FeedToJson(this);
}

好了,写完后会报错,因为FeedFromJsonFeedToJson没有找到,这个时候在控制到输入flutter packages pub run build_runner build指令后会自动生成一个moded.g.dart文件,于是在网络请求下来数据后就可以用Feed feed = Feed.fromJson(data)这个方法来将Json中数据转换保存在Feed这个实例中了.在model类中还有些复杂的Json嵌套,但是也都很简单,大家看一眼应该就会了,哈哈.JSON和序列化具体教程

5.轮播图

Flutter中的轮播图我用到了Flutter_Swiper这个组件,这里设置小圆点属性的时候稍微麻烦了点,网上好像也没有讲到,我这里讲一下. 首先要创建DotSwiperPaginationBuilder

DotSwiperPaginationBuilder builder = DotSwiperPaginationBuilder(
color: Colors.white,//未选中圆点颜色
activeColor: Colors.yellow,//选中圆点颜色
size:7,//未选中大小
activeSize: 7,//选中圆点大小
space: 5//圆点间距
);

然后在Swiper中的pagination属性中设置它

pagination: new SwiperPagination(
builder: builder,
),

  1. 网络请求 首先,展示页面要继承自StatefulWidget,因为需要动态更新数据和列表. 网络请求插件我用的Dio,非常好用. 在initState方法中请求数据表示刚加载页面的时候进行网络请求,请求数据方法如下

void getData()async{
if (lastKey == ‘0’){
dataList = [];//下拉刷新的时候将DataList制空
}
Dio dio = new Dio();
Response response = await dio.get(“ u r l url urllastKey.json”);
Reslut reslut = Reslut.fromJson(response.data);
if(!reslut.response.hasMore){
return;//如果没有数据就不继续了
}
if(reslut.response.columns != null) {
columnList = reslut.response.columns;
}
lastKey = reslut.response.lastKey;//更新lastkey
setState(() {
if (reslut.response.banners != null){
banners = reslut.response.banners;//给轮播图赋值
}
dataList.addAll(reslut.response.feeds);//给数据源赋值
});
}

因为用到了setState()方法,所以在该方法中改变了的数据会对其相应的地方进行刷新,比如设置了ListView的itemCount个数为dataList.length,如果在SetState方法中dataList.length改变了,那么ListView的itemCount树也会自动改变并刷新ListView.

7. 上拉刷新与加载

Flutter中有RefreshIndicator用于下拉刷新,它有个onRefresh闭包方法,表示下拉的时候执行的方法,一般用于网络请求.onRefresh方法如下

Future handleRefresh() {
final Completer completer = Completer();
Timer(const Duration(seconds: 1), () {
completer.complete();
});
return completer.future.then((
) {
lastKey = ‘0’;
getData();
});
}

下拉加载的话需要初始化一个ScrollController,将它设为ListView的controller,并对其进行监听,当滑动到最底部的时候进行网络请求.

@override
void initState() {
url = widget.url;
getData();
_scrollController.addListener(() {
///判断当前滑动位置是不是到达底部,触发加载更多回调
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
getData();
}
});
}
final ScrollController _scrollController = new ScrollController();

上拉加载loading框用到了flutter_spinkit插件,提供了大量的加载样式.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

代码如下

///上拉加载更多
Widget _buildProgressIndicator() {
///是否需要显示上拉加载更多的loading
Widget bottomWidget = new Row(mainAxisAlignment: MainAxisAlignment.center, children: [
///loading框
new SpinKitThreeBounce(color: Color(0xFF24292E)),
new Container(
width: 5.0,
),
]);
return new Padding(
padding: const EdgeInsets.all(20.0),
child: new Center(
child: bottomWidget,
),
);
}

8. ListView赋值

由于最上面有一个轮播图,最下面有加载框,所以ListView的itemCount个数为dataList.length+2,又因为每个item之间都有一个浅灰色的风格线,所以需要用到ListView.separated,具体代码如下:

Widget build(BuildContext context) {
return RefreshIndicator(
onRefresh:(()=> _handleRefresh()),
color: Colors.yellow,//刷新控件的颜色
child: ListView.separated(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: _getListCount(),//item个数
controller: _scrollController,//用于监听是否滑到最底部
itemBuilder: (context,index){
if(index == 0){
return SwiperWidget(context, banners);//如果是第一个,则展示banner
}else if(index < dataList.length + 1){
return WidgetUtils.GetListWidget(context, dataList[index - 1]);//展示数据
}else {
return _buildProgressIndicator();//展示加载loading框
}
},
separatorBuilder: (context,idx){//分割线
return Container(
height: 5,
color: Color.fromARGB(50,183, 187, 197),

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

最后

写到这里也结束了,在文章最后放上一个小小的福利,以下为小编自己在学习过程中整理出的一个学习思路及方向,从事互联网开发,最主要的是要学好技术,而学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯,更加需要准确的学习方向达到有效的学习效果。
由于内容较多就只放上一个大概的大纲,需要更及详细的学习思维导图的点击这里>Android IOC架构设计免费获取。
群内还有免费的高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术资料,并且还有技术大牛一起讨论交流解决问题。

方向达到有效的学习效果。
由于内容较多就只放上一个大概的大纲,需要更及详细的学习思维导图的点击这里>Android IOC架构设计免费获取。
群内还有免费的高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术资料,并且还有技术大牛一起讨论交流解决问题。**

image

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐