分享一个很炫的Periscope点赞效果
2016-03-17 15:04
288 查看
上次见到同学了做了一个非常炫的点赞动画,见猎心喜,查了查资料才知道是Periscope点赞效果,网上大神已经对此写过很容易集成的库了,今天迫不及待的想跟大家分享一下
分享大神git库地址
Periscope点赞效果
先看看大神做的效果吧
这里是项目结构
periscopelayout.java是动画所在布局,BezierEvaluator是贝塞尔计算器
整个项目可以看到这个动画的流程,
1.自定义动画布局
2.初始化爱心的缩放动画
3.爱心的随机出现,插值器的随机出现
4.爱心在滑动过程中透明度的渐变
5.滑动曲线的实现,实现贝塞尔曲线效果
PeriscopeLayout.java
贝塞尔曲线计算器BezierEvaluator.java
主页面是如何调用的呢?
这样就实现了,嗯代码不多,实现功能很简单,但原理要想搞懂就比较蛋疼了,贴上大神原文地址,
http://www.jianshu.com/p/03fdcfd3ae9c
仅供参考,源码就不上传了,就差了几张爱心的图片,大家可以稍作修改,以适应需求,谢谢大家。
分享大神git库地址
Periscope点赞效果
先看看大神做的效果吧
这里是项目结构
periscopelayout.java是动画所在布局,BezierEvaluator是贝塞尔计算器
整个项目可以看到这个动画的流程,
1.自定义动画布局
2.初始化爱心的缩放动画
3.爱心的随机出现,插值器的随机出现
4.爱心在滑动过程中透明度的渐变
5.滑动曲线的实现,实现贝塞尔曲线效果
PeriscopeLayout.java
package me.yifeiyuan.periscopelayout; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.content.Context; import android.graphics.PointF; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.AttributeSet; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.widget.ImageView; import android.widget.RelativeLayout; import java.util.Random; public class PeriscopeLayout extends RelativeLayout { private Interpolator line = new LinearInterpolator();//线性 private Interpolator acc = new AccelerateInterpolator();//加速 private Interpolator dce = new DecelerateInterpolator();//减速 private Interpolator accdec = new AccelerateDecelerateInterpolator();//先加速后减速 private Interpolator[] interpolators; private int mHeight; private int mWidth; private LayoutParams lp; private Drawable[] drawables; private Random random = new Random(); private int dHeight; private int dWidth; public PeriscopeLayout(Context context) { super(context); init(); } public PeriscopeLayout(Context context, AttributeSet attrs) { super(context, attrs); init(); } public PeriscopeLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public PeriscopeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } private void init() { //初始化显示的图片 drawables = new Drawable[3]; Drawable red = getResources().getDrawable(R.drawable.pl_red); Drawable yellow = getResources().getDrawable(R.drawable.pl_yellow); Drawable blue = getResources().getDrawable(R.drawable.pl_blue); drawables[0] = red; drawables[1] = yellow; drawables[2] = blue; //获取图的宽高 用于后面的计算 //注意 我这里3张图片的大小都是一样的,所以我只取了一个 dHeight = red.getIntrinsicHeight(); dWidth = red.getIntrinsicWidth(); //底部 并且 水平居中 lp = new LayoutParams(dWidth, dHeight); lp.addRule(CENTER_HORIZONTAL, TRUE);//这里的TRUE 要注意 不是true lp.addRule(ALIGN_PARENT_BOTTOM, TRUE); // 初始化插补器 interpolators = new Interpolator[4]; interpolators[0] = line; interpolators[1] = acc; interpolators[2] = dce; interpolators[3] = accdec; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWidth = getMeasuredWidth(); mHeight = getMeasuredHeight(); } public void addHeart() { ImageView imageView = new ImageView(getContext()); //随机选一个 imageView.setImageDrawable(drawables[random.nextInt(3)]); imageView.setLayoutParams(lp); addView(imageView); Animator set = getAnimator(imageView); set.addListener(new AnimEndListener(imageView)); set.start(); } private Animator getAnimator(View target) { AnimatorSet set = getEnterAnimtor(target); ValueAnimator bezierValueAnimator = getBezierValueAnimator(target); AnimatorSet finalSet = new AnimatorSet(); finalSet.playSequentially(set); finalSet.playSequentially(set, bezierValueAnimator); finalSet.setInterpolator(interpolators[random.nextInt(4)]); finalSet.setTarget(target); return finalSet; } private AnimatorSet getEnterAnimtor(final View target) { ObjectAnimator alpha = ObjectAnimator.ofFloat(target, View.ALPHA, 0.2f, 1f); ObjectAnimator scaleX = ObjectAnimator.ofFloat(target, View.SCALE_X, 0.2f, 1f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(target, View.SCALE_Y, 0.2f, 1f); AnimatorSet enter = new AnimatorSet(); enter.setDuration(500); enter.setInterpolator(new LinearInterpolator()); enter.playTogether(alpha, scaleX, scaleY); enter.setTarget(target); return enter; } private ValueAnimator getBezierValueAnimator(View target) { //初始化一个贝塞尔计算器- - 传入 BezierEvaluator evaluator = new BezierEvaluator(getPointF(2), getPointF(1)); //这里最好画个图 理解一下 传入了起点 和 终点 ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF((mWidth - dWidth) / 2, mHeight - dHeight), new PointF(random.nextInt(getWidth()), 0)); animator.addUpdateListener(new BezierListenr(target)); animator.setTarget(target); animator.setDuration(3000); return animator; } /** * 获取中间的两个 点 * * @param scale */ private PointF getPointF(int scale) { PointF pointF = new PointF(); pointF.x = random.nextInt((mWidth - 100));//减去100 是为了控制 x轴活动范围,看效果 随意~~ //再Y轴上 为了确保第二个点 在第一个点之上,我把Y分成了上下两半 这样动画效果好一些 也可以用其他方法 pointF.y = random.nextInt((mHeight - 100)) / scale; return pointF; } private class BezierListenr implements ValueAnimator.AnimatorUpdateListener { private View target; public BezierListenr(View target) { this.target = target; } @Override public void onAnimationUpdate(ValueAnimator animation) { //这里获取到贝塞尔曲线计算出来的的x y值 赋值给view 这样就能让爱心随着曲线走啦 PointF pointF = (PointF) animation.getAnimatedValue(); target.setX(pointF.x); target.setY(pointF.y); // 这里顺便做一个alpha动画 target.setAlpha(1 - animation.getAnimatedFraction()); } } private class AnimEndListener extends AnimatorListenerAdapter { private View target; public AnimEndListener(View target) { this.target = target; } @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); //因为不停的add 导致子view数量只增不减,所以在view动画结束后remove掉 removeView((target)); } } }
贝塞尔曲线计算器BezierEvaluator.java
package me.yifeiyuan.periscopelayout; import android.animation.TypeEvaluator; import android.graphics.PointF; public class BezierEvaluator implements TypeEvaluator<PointF> { private PointF pointF1; private PointF pointF2; public BezierEvaluator(PointF pointF1,PointF pointF2){ this.pointF1 = pointF1; this.pointF2 = pointF2; } @Override public PointF evaluate(float time, PointF startValue, PointF endValue) { float timeLeft = 1.0f - time; PointF point = new PointF();//结果 point.x = timeLeft * timeLeft * timeLeft * (startValue.x) + 3 * timeLeft * timeLeft * time * (pointF1.x) + 3 * timeLeft * time * time * (pointF2.x) + time * time * time * (endValue.x); point.y = timeLeft * timeLeft * timeLeft * (startValue.y) + 3 * timeLeft * timeLeft * time * (pointF1.y) + 3 * timeLeft * time * time * (pointF2.y) + time * time * time * (endValue.y); return point; } }
主页面是如何调用的呢?
final PeriscopeLayout periscopeLayout = (PeriscopeLayout) findViewById(R.id.periscope); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { periscopeLayout.addHeart(); } });
这样就实现了,嗯代码不多,实现功能很简单,但原理要想搞懂就比较蛋疼了,贴上大神原文地址,
http://www.jianshu.com/p/03fdcfd3ae9c
仅供参考,源码就不上传了,就差了几张爱心的图片,大家可以稍作修改,以适应需求,谢谢大家。
相关文章推荐
- uWSGI其三:uWSGI搭配Nginx使用
- 设置JDeveloper工作空间
- 深入分析Linux kernel exception框架---案例分析
- Linux crontab 定时
- CentOS RabbitMQ安装
- 【云计算】jenkins,docker,mesos,marathon,k8s相关资料
- QDesktopServices::openUrl来打开网页
- Linux的inode的理解
- CentOS下的svn强制用户提交时写日志
- 如何创建一个安全的Docker基础镜像
- Docker搭建MySQL服务
- 【Java80小白建站系列】5.网站技术的选择以及相关软件的安装
- Docker搭建MySQL服务
- 解决centos 5系统下不能上网
- linux Daemon守护进程
- 虚拟机Linux c++调用Python脚本的实现
- POSIX 线程详解
- shell脚本调试方法
- apache spark 结合 elasticsearch
- 【1】Nginx安装方法