Flutter仿掘金点赞效果

老孟导读:今天分享一下如何实现掘金点赞效果,这不仅仅是一篇技术文章,还是一篇解决问题思路的文章,遇到一个需求时,如何拆分需求,然后一步一步实现,这个过程比单纯的技术(此文)更有含金量。
先来看一下掘金点赞的效果:

说点题外话,感谢一下二哥(沉默王二 ),给了我很多建议和帮助,公众号搜索沉默王二即可关注。
遇到组合动画效果时,首先拆分一下这个动画,以掘金点赞效果为例,共分为3个动画效果:
- 小手图标改变颜色并且缩放一下。
- 圆环由粗变细,透明度逐渐变为0。
- 最外圈小点点透明度逐渐变为0。
拆分好了之后,就一步一步实现其效果。
小手缩放效果
小手缩放效果需要2个图标,选中和未选中两种状态,我从阿里的图标库中选了2个类似的图标(未找到一摸一样的)。两种状态的图标定义如下:
///
/// 未点赞icon
///
const Icon _unLikeIcon = Icon(
IconData(0xe60a, fontFamily: 'appIconFonts'),
);
///
/// 点赞icon
///
const Icon _likeIcon = Icon(
IconData(0xe60c, fontFamily: 'appIconFonts'),
color: Color(0xFF1afa29),
);
关于如何使用阿里的图标库中的图标可以查看此文章。
由于小手图标的动画效果是放大->还原,使用组合动画实现其效果,代码如下:
@override
initState() {
_animationController =
AnimationController(duration: Duration(milliseconds: 300), vsync: this);
_iconAnimation = Tween(begin: 1.0, end: 1.3).animate(_animationController);
_iconAnimation = TweenSequence([
TweenSequenceItem(
tween: Tween(begin: 1.0, end: 1.3)
.chain(CurveTween(curve: Curves.easeIn)),
weight: 50),
TweenSequenceItem(tween: Tween(begin: 1.3, end: 1.0), weight: 50),
]).animate(_animationController);
}
@override
Widget build(BuildContext context) {
return _buildLikeIcon();
}
_buildLikeIcon() {
return ScaleTransition(
scale: _iconAnimation,
child: widget.like
? IconButton(
padding: EdgeInsets.all(0),
icon: _likeIcon,
onPressed: () {
_clickIcon();
},
)
: IconButton(
padding: EdgeInsets.all(0),
icon: _unLikeIcon,
onPressed: () {
_clickIcon();
},
),
);
}
添加按钮点击效果:
_clickIcon() {
if (_iconAnimation.status == AnimationStatus.forward ||
_iconAnimation.status == AnimationStatus.reverse) {
return;
}
setState(() {
widget.like = !widget.like;
});
if (_iconAnimation.status == AnimationStatus.dismissed) {
_animationController.forward();
} else if (_iconAnimation.status == AnimationStatus.completed) {
_animationController.reverse();
}
}

圆环动画
圆环的动画效果是线条宽度逐渐变为0,透明度逐渐变为0,相对简单,使用AnimatedBuilder实现:
_buildCircle() {
return !widget.like
? Container()
: AnimatedBuilder(
animation: _circleAnimation,
builder: (BuildContext context, Widget child) {
return Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: Color(0xFF5FA0EC)
.withOpacity(_circleAnimation.value),
width: _circleAnimation.value * 8)),
);
},
);
}
定义_circleAnimation:
_circleAnimation =
Tween(begin: 1.0, end: 0.0).animate(_animationController);

最外圈小点点
最外圈的小点点动画效果是最简单的,透明度逐渐变为0,但布局相对复杂,围绕小手形成一个圆形,使用Flow实现此布局,Flow是一个非常酷炫的布局组件,更多用法查看此文。
构建单个小圆点
_buildCirclePoint(double radius, Color color) {
return !widget.like
? Container()
: AnimatedBuilder(
animation: _circleAnimation,
builder: (BuildContext context, Widget child) {
return Container(
width: radius,
height: radius,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: color.withOpacity(_circleAnimation.value)),
);
},
);
}
构建围绕小手的多个点:
_buildCirclePoints() {
return Flow(
delegate: CirclePointFlowDelegate(),
children: <Widget>[
_buildCirclePoint(2, Color(0xFF97B1CE)),
_buildCirclePoint(5, Color(0xFF4AC6B7)),
_buildCirclePoint(2, Color(0xFF97B1CE)),
_buildCirclePoint(5, Color(0xFF4AC6B7)),
_buildCirclePoint(2, Color(0xFF97B1CE)),
_buildCirclePoint(5, Color(0xFF4AC6B7)),
_buildCirclePoint(2, Color(0xFF97B1CE)),
_buildCirclePoint(5, Color(0xFF4AC6B7)),
_buildCirclePoint(2, Color(0xFF97B1CE)),
_buildCirclePoint(5, Color(0xFF4AC6B7)),
_buildCirclePoint(2, Color(0xFF97B1CE)),
_buildCirclePoint(5, Color(0xFF4AC6B7)),
_buildCirclePoint(2, Color(0xFF97B1CE)),
_buildCirclePoint(5, Color(0xFF4AC6B7)),
_buildCirclePoint(2, Color(0xFF97B1CE)),
_buildCirclePoint(5, Color(0xFF4AC6B7)),
],
);
}
CirclePointFlowDelegate 定义如下:
class CirclePointFlowDelegate extends FlowDelegate {
CirclePointFlowDelegate();
@override
void paintChildren(FlowPaintingContext context) {
var radius = min(context.size.width, context.size.height) / 2.0;
//中心点
double rx = radius;
double ry = radius;
for (int i = 0; i < context.childCount; i++) {
if (i % 2 == 0) {
double x =
rx + (radius - 5) * cos(i * 2 * pi / (context.childCount - 1));
double y =
ry + (radius - 5) * sin(i * 2 * pi / (context.childCount - 1));
context.paintChild(i, transform: Matrix4.translationValues(x, y, 0));
} else {
double x = rx +
(radius - 5) *
cos((i - 1) * 2 * pi / (context.childCount - 1) +
2 * pi / ((context.childCount - 1) * 3));
double y = ry +
(radius - 5) *
sin((i - 1) * 2 * pi / (context.childCount - 1) +
2 * pi / ((context.childCount - 1) * 3));
context.paintChild(i, transform: Matrix4.translationValues(x, y, 0));
}
}
}
@override
bool shouldRepaint(FlowDelegate oldDelegate) => true;
}

交流
老孟Flutter博客地址(近200个控件用法):http://laomengit.com
欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:
![]() |
![]() |
Flutter仿掘金点赞效果的更多相关文章
- Android -- 自定义ViewGroup+贝塞尔+属性动画实现仿QQ点赞效果
1,昨天我们写了篇简单的贝塞尔曲线的应用,今天和大家一起写一个QQ名片上常用的给别人点赞的效果,实现效果图如下: 红心的图片比较丑,见谅见谅(哈哈哈哈哈哈).... 2,实现的思路和原理 从上面的效果 ...
- Android -- 《 最美有物》好看的点赞效果
1,前天在鸿洋的公众号上看到一款不错的点赞效果,是仿最美有物的点赞,再加上自己最近学习状态很差,自己想着通过这个效果练手一下,果然,花了整整两天的时间,按照以前的效率的话一天就够了,哎,已经调整了一个 ...
- Flutter 仿滴滴出行App
绿色出行 Flutter 仿滴滴出行App 地图:采用高德地图,仅简单完成了部分功能,基础地图,地址检索,逆地理编码. 界面:仿滴滴主界面,地图中心请求动效果,服务tabs展开效果,地址检索界面,城市 ...
- Android仿IOS回弹效果 ScrollView回弹 总结
Android仿IOS回弹效果 ScrollView回弹 总结 应项目中的需求 须要仿IOS 下拉回弹的效果 , 我在网上搜了非常多 大多数都是拿scrollview 改吧改吧 试了一些 发现总 ...
- PHP实现仿Google分页效果的分页函数
本文实例讲述了PHP实现仿Google分页效果的分页函数.分享给大家供大家参考.具体如下: /** * 分页函数 * @param int $total 总页数 * @param int $pages ...
- Android类似Periscope点赞效果
原文 https://github.com/AlanCheen/PeriscopeLayout 主题 安卓开发 PeriscopeLayout A layout with animation li ...
- 原生wcPop.js消息提示框(移动端)、内含仿微信弹窗效果
wcPop.js移动端消息对话框插件是之前的wxPop.js的升级版,优化了js和css,并且新增了仿微信弹窗效果, 是一款含有多种情景模式的原生模态消息对话框代码,可用于替代浏览器默认的alert弹 ...
- EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象
EF+LINQ事物处理 在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作 ...
- jquery 仿windows10菜单效果下载
http://www.kuitao8.com/20150923/4079.shtml jquery 仿windows10菜单效果下载
随机推荐
- php时间:获取上一个月,本月天数,下一个月
时间戳转日期 date() 日期转时间戳 strtotime() 当前时间戳time() 获取当前月的天数: $i=; $y=; echo date("t",strtotime(& ...
- 安装 wbemcli
安装环境 建立自己的目录后, wget http://vault.centos.org/6.0/os/x86_64/Packages/sblim-wbemcli- ...
- springboot中Redis的Lettuce客户端和jedis客户端
1.引入客户端依赖 <!--jedis客户端依赖--> <dependency> <groupId>redis.clients</groupId> &l ...
- 听说你在从事前端开发?那这10个JavaScript的优化问题你不得不知道!
JavaScript的高效优化一直都是我们前端开发中非常重要的工作,也是很多开发人员无法做好的一部分内容,今天我总结了10个优化问题,大家可以参考来做优化,这其中很多问题都是大家经常遇到的哦. ==和 ...
- TypeScript 2.0 正式发布
9 月 22 日,TypeScript 2.0 正式发布了. TypeScript 是微软开发的开源的编程语言,主要负责人是 C# 之父 Anders Hejlsberg. TypeScript 成功 ...
- tomcat8调优
a. tomcat的运行原理: 1. Tomcat是运行在JVM中的一个进程.它定义为[中间件],顾名思义,是一个在Java项目与JVM之间的中间容器. 2. Web项目的本质,是一大堆的资源文件和方 ...
- c/c++获取文件夹下所有文件名
如何获取某一文件夹下所有文件名,是一个很有意思的问题.网上代码很多,找了个简单的,特此收录. #include <iostream> #include <io.h> #incl ...
- 首次使用AWS服务器EC2
AWS有一年的免费套餐,这个便宜我得占. 申请的时候需要填写银行卡,AWS暂不支持储蓄卡,只好绑信用卡了. 创建EC2实例之后,下一个要解决的问题就是远程root访问. 1. 修改安全组设置 2. s ...
- Java笔记(day13)
多线程: 进程:正在进行中的程序(直译) 线程:执行路径,就是进程中负责程序执行的控制单元(执行路径): 一个进程中可以多个路径,称为多线程 一个进程至少一个线程 每一个线程都有自己运行的内容,这个内 ...
- django3开发完整博客带评价
纯django开发最完美博客 2020年5月打造最时尚博客系统教程 为了学习速度,集中精力学习django和博客开发, 没有使用其它框架,也没有使用css预处理等 这样学起来最方便, 博客前后端都完成 ...

