Flutter仿京东实战项目一-首页header

218 阅读3分钟

好久好久没写代码了,由于最近可能要找工作,所以我准备找个项目写写练练手、找找写代码的感觉。由于我又是个喜新厌旧的人,所以准备找个我不熟的Flutter来写写。

京东我用的比较多,所以我准备用Flutter仿一个,尽量做到一比一还原功能

写这个文章的原则和内容

  • 类似简单布局的东西都是一带而过、毕竟这些东西我们只要多试试就能写对了
  • 能用现成的组件和开源库,就一定不自己写
  • 我很懒、不会讲具体代码实现,但是我会把思路步骤过程记录下来
  • 会记录下我实现功能中遇到的各种坑和有意思的地方
  • 我写的很随意,想到啥写到啥,可能会忘了很多东西,后来会补上

代码地址:github.com/nppp1990/jd…

因为代码还在更新,所以现在还是半成品;我会边更新代码边更新文章的

功能点

京东 image.png

最终实现效果 jt1.gif

  • UI布局
  • 左上角满减文本的滚动动画
  • 中间tab的切换动画
  • 搜索框的文本的自动刷新

UI布局

  • 整体用Column实现上下布局
  • 上面的跨店满减、居中tab、消息按钮用Stack+Align分别实现:居左、居中、居右
  • 下面搜索框用Container包裹实现圆角
    • child为Row从左到右布局
    • 中间文本用Expanded包裹

总结下我碰到的问题和坑

文本的滚动动画

右上角的文本滚动动画可以用flutter自带的PageView来实现,但是PageView不支持循环滚动 所以pub上搜索”loop pageview“:找到loop_page_view

用法很简单、代码和注释如下 image.png

然后实现自动触发滚动、需要用到Timer

_timer = Timer.periodic(const Duration(seconds: 2), (timer) {
  _pageController.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.easeInOut);
});

tab的切换动画

  • tab文字一直能看见
  • 动画开始后,按钮大小随之变小变大
  • 切换完成后、文字颜色发生变化

可选方案

  1. 方案一:flutter自带的Switch:内容不是文本
  2. 方案二:flutter自带的TabBar:动画不太对
  3. 方案三:pub上搜”custom Switch“:没有满足要求的库
  4. 方案四:自定义动画实现

按钮动画分为两个部分

  • 位移动画
  • 宽度变化动画

image.png

  • 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();
}

最后加上监听回调和文本颜色变化

image.png

搜索框文本自动刷新

这里不需要动画,直接用Timer定时刷新文本即可

image.png