好久好久没写代码了,由于最近可能要找工作,所以我准备找个项目写写练练手、找找写代码的感觉。由于我又是个喜新厌旧的人,所以准备找个我不熟的Flutter来写写。
京东我用的比较多,所以我准备用Flutter仿一个,尽量做到一比一还原功能
写这个文章的原则和内容
- 类似简单布局的东西都是一带而过、毕竟这些东西我们只要多试试就能写对了
- 能用现成的组件和开源库,就一定不自己写
- 我很懒、不会讲具体代码实现,但是我会把思路和步骤过程记录下来
- 会记录下我实现功能中遇到的各种坑和有意思的地方
- 我写的很随意,想到啥写到啥,可能会忘了很多东西,后来会补上
因为代码还在更新,所以现在还是半成品;我会边更新代码边更新文章的
功能点
京东
最终实现效果
- 横向滑动的分类列表
- 支持横滑
- 点击item后文字变黑、变大
- 点击item后对应item移到列表中间
- 图片banner
- 两行的横滑列表
- 支持横滑
- item右上角的mask
- 底部指示器
横向滑动的分类列表
方案一:ListView实现
- 横滑:
scrollDirection: Axis.horizontal, - 选中态变化:加一个变量
late int _selectedIndex;保存选中的item下标,通过setState更新index来控制选中变化 - 点击item后对应item移到列表中间:可参考
TabController(计算滑动的位置实在有点麻烦,所以我没尝试)
方案二:TabBar实现
- 横滑、点击item自动移到中间:TabBar自带就能实现
- 点击item后文字变黑、变大:需要分别修改下面几个属性即可
labelColor: Colors.black,
labelStyle: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
unselectedLabelColor: grey1,
unselectedLabelStyle: const TextStyle(fontSize: 16),
TabBar的坑
- 删除TabBar自带padding:
labelPadding: EdgeInsets.zero - Tabbar的item如果做了监听事件的监听,那么自带的移动到中间功能就会被屏蔽掉;如果想监听点击事件、可以用TabBar的
onTap来实现 - 删除TabBar底部的Indicator:参考这个stackoverflow.com/questions/5… 上面链接的方法都不好使,试了下修改下图几个地方好使
两行的横滑列表
显然这个用最外层需要用PageView实现
Grid布局
这里有两个坑需要注意的
- GridView自带paddingTop需要删掉
- grid item的高度设置是不生效的,而是通过宽度和
childAspectRatio计算出来的。所以假设期望的高度为itemHeight,那么childAspectRatio需要这么算
double childAspectRatio = getScreenWidth(context) / (5 * itemHeight);
grid item右上角的闪现mask动画
- 布局就用
Container的BoxDecoration分别实现圆角和白线 - 动画可以用
ScaleTransition实现从0到1,1到0- 从0到1:
_controller.forward(); - 从1到0:
_controller.reverse();
- 从0到1:
- 文本通过index+1循环改变
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: widget.animationDuration * 0.5);
_animation = Tween(begin: 1.0, end: 0.0).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut))
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
setState(() {
_index = (_index + 1) % widget.data.length;
});
} else if (status == AnimationStatus.dismissed) {
Future.delayed(widget.interval, () {
_controller.forward();
});
}
});
Future.delayed(widget.interval, () {
_controller.forward();
});
}
底部Indicator
直接pub上搜索:”page indicator“选用的人最多的smooth_page_indicator
samples里有我们想要的例子
最终实现代码和注释如下图