高度关注并申明 [加群],进Android控制技术群
.jpg)
类型:控制技术
念完约需
4
两分钟
同中书门生左丞相事jaren
http://blog.csdn.net/L_wwbs/article/details/72781717
一 序言
透过自订命令行,欲仿效 Twitter 的雅雷效用。主要就牵涉:
三次贝塞尔曲线应用;
属性动画的综合应用;
自订View流程.
二 拆解原效用
我们先看一下 Twitter 上的原版效用是怎样的,放大后:
.jpg)
好吧!原速的看不太清楚,逐帧延迟后:
.jpg)
因为这个效用有需要使用多个动画杂糅而成,为了更确切得出每个子动画阶段所占比例,还是用PS大法把它打开,根据该阶段的帧数以及总帧数来确定动画时长如何分配:
.jpg)
三 实现
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;}四 最终效用
.jpg)
五 总结
这里大致实现了Twitter的雅雷效用。虽然是根据原效用图像帧比例来确定动画应分配时间的,放慢观察似乎还是不太理想。另有些状态确定不了是颜色渐变还是透明度变化,临界消失时缩放有没有伴随移动,这些都从简处理了。
需要强调一下的是这里用到了颜色渐变动画,而这个方法系统是 API21 才提供的,这里直接拷贝系统源码的 ArgbEvaluator 到项目里了,其实就相当于属性动画自订 TypeEvaluator,既然源码里有,就不客气了。
源码:https://github.com/qkxyjren/LikeView
以上。感谢阅读。坚持用心分享,你的雅雷 或 转发分享是对我最大的鼓励,还望多多留言交流。
.jpg)
感谢 雅雷 or 转发分享,别忘了高度关注哈
.jpg)
金狗推特粉丝点赞转推自助买粉网站
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)

.jpg)
.jpg)
.jpg)
.jpg)

.jpg)
.jpg)

.jpg)
.jpg)

.jpg)

.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)

.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)

.jpg)
.jpg)



.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)

.jpg)
.jpg)

.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)



.jpg)
.jpg)
.jpg)

.jpg)
.jpg)

.jpg)
.jpg)
.jpg)
.jpg)
.jpg)
.jpg)








.jpg)
.jpg)

.jpg)
.jpg)


.jpg)






.jpg)













.jpg)









.jpg)

.jpg)





.jpg)










.jpg)




.jpg)







.jpg)

.jpg)
.jpg)


.jpg)





















