高度关注并申明 [加群],进Android控制技术群
类型:控制技术
念完约需
4
两分钟
同中书门生左丞相事jaren
http://blog.csdn.net/L_wwbs/article/details/72781717
一 序言
透过自订命令行,欲仿效 Twitter 的雅雷效用。主要就牵涉:
三次贝塞尔曲线应用;
属性动画的综合应用;
自订View流程.
二 拆解原效用
我们先看一下 Twitter 上的原版效用是怎样的,放大后:
好吧!原速的看不太清楚,逐帧延迟后:
因为这个效用有需要使用多个动画杂糅而成,为了更确切得出每个子动画阶段所占比例,还是用PS大法把它打开,根据该阶段的帧数以及总帧数来确定动画时长如何分配:
三 实现
3.1 动画控制
这里使用ValueAnimator并设置插值器为LinearInterpolator来获得随时间正比例变化的逐渐增大的整数值。这个整数值在这里有三个作用:
每监听到一个整数值变化重绘一次View。
根据整数值的大小范围来划分所处的不同阶段,这里共划分为五个状态:
绘制心形并伴随缩小和颜色渐变;
绘制圆并伴随放大和颜色渐变;
绘制圆环并伴随放大和颜色渐变;
圆环减消失、心形放大、周围环绕十四圆点;
环绕的十四圆点向外移动并缩小、透明度渐变、渐隐;
以整数值为基础来实现其他动画效用避免出现大量的 ObjectAnimator。
/*** 展现View点击后的变化效用*/privatevoidstartViewMotion() {if(animatorTime !=null&& animatorTime.isRunning()){return;}resetState();animatorTime = ValueAnimator.ofInt(0,1200);animatorTime.setDuration(mCycleTime);//需要随时间匀速变化animatorTime.setInterpolator(newLinearInterpolator());animatorTime.start();animatorTime.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {@OverridepublicvoidonAnimationUpdate(ValueAnimator animation) {int animatedValue = (int) animation.getAnimatedValue();if(animatedValue ==0) {if(animatorArgb ==null|| !animatorArgb.isRunning()) {animatorArgb = ofArgb(mDefaultColor,0Xfff74769,0Xffde7bcc);animatorArgb.setDuration(mCycleTime *28/120);animatorArgb.setInterpolator(newLinearInterpolator());animatorArgb.start();}}elseif(animatedValue <=100) {float percent = calcPercent(0f,100f, animatedValue);mCurrentRadius = (int) (mRadius - mRadius * percent);if(animatorArgb !=null&& animatorArgb.isRunning())mCurrentColor = (int) animatorArgb.getAnimatedValue();mCurrentState = HEART_VIEW;invalidate();}elseif(animatedValue <=280) {float percent = calcPercent(100f,340f, animatedValue);//此阶段未达到最大半径[编辑 by Android 进阶之旅]mCurrentRadius = (int) (2* mRadius * percent);if(animatorArgb !=null&& animatorArgb.isRunning())mCurrentColor = (int) animatorArgb.getAnimatedValue();mCurrentState = CIRCLE_VIEW;invalidate();}elseif(animatedValue <=340) {//半径接上一阶段增加,此阶段外环半径已经最大值float percent = calcPercent(100f,340f,animatedValue);//用于计算圆环宽度,最小0.2,与动画进度负相关mCurrentPercent =1f - percent +0.2f >1f ?1f :1f - percent +0.2f;mCurrentRadius = (int) (2* mRadius * percent);if(animatorArgb !=null&& animatorArgb.isRunning())mCurrentColor = (int) animatorArgb.getAnimatedValue();mCurrentState = RING_VIEW;invalidate();}elseif(animatedValue <=480) {//内环半径增大直至消亡float percent = calcPercent(340f,480f, animatedValue);mCurrentPercent = percent;//外环半径不再改变mCurrentRadius = (int) (2* mRadius);mCurrentState = RING_DOT__HEART_VIEW;invalidate();}elseif(animatedValue <=1200) {float percent = calcPercent(480f,1200f, animatedValue);mCurrentPercent = percent;mCurrentState = DOT__HEART_VIEW;if(animatedValue ==1200) {animatorTime.cancel();animatorTime.removeAllListeners();state =true;}invalidate();}}});}3.2 图形绘制
1. 心形
这里使用贝塞尔曲线来绘制心形,透过四组控制点的改变来拟合心形。当然项目中为了方便此处的绘制可以用图片代替。
//绘制心形privatevoiddrawHeart(Canvas canvas, int radius, int color) {initControlPoints(radius);mPaint.setColor(color);mPaint.setAntiAlias(true);mPaint.setStyle(Paint.Style.FILL);Path path =newPath();path.moveTo(tPointB.x, tPointB.y);path.cubicTo(tPointC.x, tPointC.y, rPointA.x, rPointA.y, rPointB.x, rPointB.y);path.cubicTo(rPointC.x, rPointC.y, bPointC.x, bPointC.y, bPointB.x, bPointB.y);path.cubicTo(bPointA.x, bPointA.y, lPointC.x, lPointC.y, lPointB.x, lPointB.y);path.cubicTo(lPointA.x, lPointA.y, tPointA.x, tPointA.y, tPointB.x, tPointB.y);canvas.drawPath(path, mPaint);}2 其他
还有一些 圆、圆点、圆环的绘制比较简单这里不再列出,重点是这些图形叠加交错的动画变化。
3.3 点击事件
对外提供点击事件监听,以便处理雅雷与取消雅雷的逻辑:
@Overridepublic boolean onTouchEvent(MotionEvent event) {int x = (int) event.getX();int y = (int) event.getY();int action = event.getAction();switch(action) {caseMotionEvent.ACTION_DOWN:break;caseMotionEvent.ACTION_MOVE:break;caseMotionEvent.ACTION_UP:if(x + getLeft() < getRight() && y + getTop() < getBottom()) {//点击在View区域内if(state) {deselectLike();}else{startViewMotion();}if(mListener !=null)mListener.onClick(this);}break;}returntrue;}对外提供设置监听的方法
@OverridepublicvoidsetOnClickListener(@Nullable OnClickListener l) {mListener = l;}获取是否已雅雷的状态
/*** Indicates whether this LikeView is selected or not.** @return true if the LikeView is selected now, false is deselected*/public boolean getState() {returnthis.state;}四 最终效用
五 总结
这里大致实现了Twitter的雅雷效用。虽然是根据原效用图像帧比例来确定动画应分配时间的,放慢观察似乎还是不太理想。另有些状态确定不了是颜色渐变还是透明度变化,临界消失时缩放有没有伴随移动,这些都从简处理了。
需要强调一下的是这里用到了颜色渐变动画,而这个方法系统是 API21 才提供的,这里直接拷贝系统源码的 ArgbEvaluator 到项目里了,其实就相当于属性动画自订 TypeEvaluator,既然源码里有,就不客气了。
源码:https://github.com/qkxyjren/LikeView
以上。感谢阅读。坚持用心分享,你的雅雷 或 转发分享是对我最大的鼓励,还望多多留言交流。
感谢 雅雷 or 转发分享,别忘了高度关注哈