好久好久没写代码了,由于最近可能要找工作,所以我准备找个项目写写练练手、找找写代码的感觉。由于我又是个喜新厌旧的人,所以准备找个我不熟的Flutter来写写。
京东我用的比较多,所以我准备用Flutter仿一个,尽量做到一比一还原功能
写这个文章的原则和内容
- 类似简单布局的东西都是一带而过、毕竟这些东西我们只要多试试就能写对了
- 能用现成的组件和开源库,就一定不自己写
- 我很懒、不会讲具体代码实现,但是我会把思路和步骤过程记录下来
- 会记录下我实现功能中遇到的各种坑和有意思的地方
- 我写的很随意,想到啥写到啥,可能会忘了很多东西,后来会补上
因为代码还在更新,所以现在还是半成品;我会边更新代码边更新文章的
功能点
京东
最终实现效果
- UI布局
- 左上角满减文本的滚动动画
- 中间tab的切换动画
- 搜索框的文本的自动刷新
UI布局
- 整体用
Column实现上下布局 - 上面的跨店满减、居中tab、消息按钮用Stack+Align分别实现:居左、居中、居右
- 下面搜索框用
Container包裹实现圆角- child为
Row从左到右布局 - 中间文本用
Expanded包裹
- child为
总结下我碰到的问题和坑
- 高度、宽度布局问题搜索关键字”flutter wrap_content“):the-equivalent-of-wrap-content-and-match-parent-in-flutter
- Stack布局如何居中(搜索关键字”stack center“):Flutter position stack widget in center
- 如何使用Icon:在Flutter中使用自定义Icon
文本的滚动动画
右上角的文本滚动动画可以用flutter自带的PageView来实现,但是PageView不支持循环滚动
所以pub上搜索”loop pageview“:找到loop_page_view
用法很简单、代码和注释如下
然后实现自动触发滚动、需要用到Timer
_timer = Timer.periodic(const Duration(seconds: 2), (timer) {
_pageController.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.easeInOut);
});
tab的切换动画
- tab文字一直能看见
- 动画开始后,按钮大小随之变小变大
- 切换完成后、文字颜色发生变化
可选方案
- 方案一:flutter自带的
Switch:内容不是文本 - 方案二:flutter自带的
TabBar:动画不太对 - 方案三:pub上搜”custom Switch“:没有满足要求的库
- 方案四:自定义动画实现
按钮动画分为两个部分
- 位移动画
- 宽度变化动画
- offset的初始值为0,结束值为textWidth1+padding
- width的初始值为textWidth1,结束值为textWidth2
文本宽度的可以利用paint来计算(类似Android的measureText)
final style = DefaultTextStyle.of(context).style.merge(TextStyle(fontSize: _textFont));
final painter1 = TextPainter(
text: TextSpan(text: widget.textOn, style: style),
textDirection: TextDirection.ltr,
textScaleFactor: MediaQuery.of(context).textScaleFactor,
)..layout();
_onTextSize = painter1.size;
final painter2 = TextPainter(
text: TextSpan(text: widget.textOff, style: style),
textDirection: TextDirection.ltr,
textScaleFactor: MediaQuery.of(context).textScaleFactor,
)..layout();
_offTextSize = painter2.size;
注意这个paint计算必须在build函数里调用
向左的动画为forward、向右的动画为reverse
if (isTapOn) {
_animationController.reverse();
} else {
_animationController.forward();
}
最后加上监听回调和文本颜色变化
搜索框文本自动刷新
这里不需要动画,直接用Timer定时刷新文本即可