安卓 自己动手实现守望先锋动画
2016-11-11 10:03
399 查看
起因:因为逛CSDN的时候无意间看到这篇博文(传送门),想给自己的项目加上这个加载效果,但是原谅我放荡不羁用不来(不知道为什么是用那个报一堆不知名的错误),于是我决定自己动手,丰衣足食。
先上效果:
截图不是gif,请见谅。
下面来实现:(绘制一个正六边形我就不再多说)
先来绘制出所有的六边形:
按照上图所示:
六边形在没有x和y的偏移量的情况下,假设我们从左边的第一个定点开始绘制的话,那么
六边形的高等于:Math.sqrt(3)*六边形边长。
第一个出现位置的起始点坐标是:(六边形的高/2,六边形边长/2)。
第二个出现位置的起始点坐标是:((六边形的高/2)*3,六边形的边长/2).
第三个出现位置的起始点坐标是:(六边形的高*2,(六边形的边长/2)*3).
第四个出现位置的起始点坐标是:((六边形的高/2)*3,六边形边长*3).
第五个出现位置的起始点坐标是:(六边形的高/2,六边形边长*3).
第六个出现位置的起始点坐标是:(0,(六边形的边长/2)*3).
第七个出现位置的起始点坐标是:(六边形的高,(六边形的边长/2)*3).
其他点的计算就不一一列举了,都是很简单的数学计算。
先讲动画:
这里有一个动画,一种是显示的,一种隐藏的,但是隐藏的可以用显示的动画reverse()来实现逆向动画。
下面是动画代码:
添加动画监听:
现在可以来看看绘画代码了(代码很简单,必要的地方我已经加上了注释):
接下来就要实现ondraw()方法了:
实现构造方法(在这里对画笔,绘画大小,动画等进行初始化):
当然,我们需要外部可以控制这些动画的播放,加上几个方法应该就可以了(并没有测试)。
源码传送门(传送门)
先上效果:
截图不是gif,请见谅。
下面来实现:(绘制一个正六边形我就不再多说)
先来绘制出所有的六边形:
按照上图所示:
六边形在没有x和y的偏移量的情况下,假设我们从左边的第一个定点开始绘制的话,那么
六边形的高等于:Math.sqrt(3)*六边形边长。
第一个出现位置的起始点坐标是:(六边形的高/2,六边形边长/2)。
第二个出现位置的起始点坐标是:((六边形的高/2)*3,六边形的边长/2).
第三个出现位置的起始点坐标是:(六边形的高*2,(六边形的边长/2)*3).
第四个出现位置的起始点坐标是:((六边形的高/2)*3,六边形边长*3).
第五个出现位置的起始点坐标是:(六边形的高/2,六边形边长*3).
第六个出现位置的起始点坐标是:(0,(六边形的边长/2)*3).
第七个出现位置的起始点坐标是:(六边形的高,(六边形的边长/2)*3).
其他点的计算就不一一列举了,都是很简单的数学计算。
先讲动画:
这里有一个动画,一种是显示的,一种隐藏的,但是隐藏的可以用显示的动画reverse()来实现逆向动画。
下面是动画代码:
mShowAni = ValueAnimator.ofFloat(0,1); mShowAni.setDuration(200); mShowAni.setInterpolator(new DecelerateInterpolator()); mShowAni.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){ @Override public void onAnimationUpdate(ValueAnimator animation){ float value = (float)animation.getAnimatedValue(); mScale = 0.5f+value/2; mPaint.setAlpha((int)(value*255)); invalidate();//更新 } });
添加动画监听:
mShowAni.addListener(new Animator.AnimatorListener(){ @Override public void onAnimationStart(Animator animation){ } @Override public void onAnimationEnd(Animator animation){ mShowAni.removeAllListeners(); mShowAni = null; initAni(); if(drawNum!=8) { backDrawNum = 8;//赋值回退动画的位置 drawNum++;//正向动画的位置自增1 } if(drawNum==8 && backDrawNum!=0) { //开始播放逆向动画 backDrawNum--; mShowAni.reverse(); } else if(drawNum==8 && backDrawNum==0) { //逆向动画播放完毕,播放正向动画 drawNum = 1; } invalidate(); } @Override public void onAnimationCancel(Animator animation){ } @Override public void onAnimationRepeat(Animator animation){ } });
现在可以来看看绘画代码了(代码很简单,必要的地方我已经加上了注释):
public void DrawSix(Canvas canvas,Paint paint,int mLength,float Xoffset,float Yoffset,float scale) { Path mPath = new Path(); float height = (float)(Math.sqrt(3)*mLength); mPath.moveTo(Xoffset,Yoffset+mLength/2);//初始点 mPath.lineTo(Xoffset+height/2,Yoffset); mPath.lineTo(Xoffset+height,Yoffset+mLength/2); mPath.lineTo(Xoffset+height,Yoffset+(mLength/2)*3); mPath.lineTo(Xoffset+height/2,Yoffset+mLength*2); mPath.lineTo(Xoffset,Yoffset+(mLength/2)*3); mPath.lineTo(Xoffset,Yoffset+mLength/2); mPath.close();//闭合路径 //Log.i("动画里","mScale:"+mScale); if(scale!=-1) {//防止动画重复播放 if(mShowAni != null && ! mShowAni.isRunning()) { mShowAni.start(); } canvas.save(); canvas.scale(scale,scale,Xoffset + height / 2,Yoffset + mLength); canvas.drawPath(mPath,paint); canvas.restore(); } else { //==-1的时候不播放动画,不处理会导致画面闪动 canvas.save(); canvas.scale(1,1,Xoffset + height / 2,Yoffset + mLength); canvas.drawPath(mPath,paint); canvas.restore(); } } /** * 画守望六边形 * @param canvas * @param paint * @param mLength 半径 * @param Xoffset 偏移量 * @param Yoffset Y偏移量 * @param drawNum 绘画的位置 */ public void DrawOWSix(Canvas canvas,Paint paint,int mLength,float Xoffset,float Yoffset,int drawNum,int backNum) { float height = (float)(Math.sqrt(3)*mLength); float XoffsetZero = Xoffset; float XoffsetOne = Xoffset+height/2; float YoffsetOne = Yoffset; float XoffsetTwo = Xoffset+(height/2)*3; float XoffsetThree = Xoffset+height*2; float YoffsetTwo = Yoffset+(mLength/2)*3; float YoffsetThree = Xoffset+mLength*3; float XoffsetCenter = Xoffset+height; Paint defaultPaint = paint;//用来绘制已经播放完成动画的六边形 paint.setAlpha(255); if(drawNum==8) { drawNum = backNum; } //画六边形,里面的-1赋值是用来让动画不再播放的 switch(drawNum) { case 1: DrawSix(canvas,paint,mLength,XoffsetOne,YoffsetOne,mScale); break; case 2: DrawSix(canvas,defaultPaint,mLength,XoffsetOne,YoffsetOne,-1); DrawSix(canvas,paint,mLength,XoffsetTwo + 3,YoffsetOne,mScale); break; case 3: DrawSix(canvas,defaultPaint,mLength,XoffsetOne,YoffsetOne,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetTwo + 3,YoffsetOne,-1); DrawSix(canvas,paint,mLength,XoffsetThree + 6,YoffsetTwo + 3,mScale); break; case 4: DrawSix(canvas,defaultPaint,mLength,XoffsetOne,YoffsetOne,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetTwo + 3,YoffsetOne,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetThree + 6,YoffsetTwo + 3,-1); DrawSix(canvas,paint,mLength,XoffsetTwo + 6,YoffsetThree + 6,mScale); break; case 5: DrawSix(canvas,defaultPaint,mLength,XoffsetOne,YoffsetOne,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetTwo + 3,YoffsetOne,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetThree + 6,YoffsetTwo + 3,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetTwo + 6,YoffsetThree + 6,-1); DrawSix(canvas,paint,mLength,XoffsetOne + 3,YoffsetThree + 6,mScale); break; case 6: DrawSix(canvas,defaultPaint,mLength,XoffsetOne,YoffsetOne,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetTwo + 3,YoffsetOne,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetThree + 6,YoffsetTwo + 3,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetTwo + 6,YoffsetThree + 6,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetOne + 3,YoffsetThree + 6,-1); DrawSix(canvas,paint,mLength,XoffsetZero,YoffsetTwo + 3,mScale); break; case 7: DrawSix(canvas,defaultPaint,mLength,XoffsetOne,YoffsetOne,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetTwo + 3,YoffsetOne,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetThree + 6,YoffsetTwo + 3,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetTwo + 6,YoffsetThree + 6,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetOne + 3,YoffsetThree + 6,-1); DrawSix(canvas,defaultPaint,mLength,XoffsetZero,YoffsetTwo + 3,-1); DrawSix(canvas,paint,mLength,XoffsetCenter + 3,YoffsetTwo + 3,mScale); break; default: break; } }
接下来就要实现ondraw()方法了:
@Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); this.canvas = canvas; DrawOWSix(this.canvas,mPaint,mLength,XOffset,YOffset,drawNum,backDrawNum); }
实现构造方法(在这里对画笔,绘画大小,动画等进行初始化):
public DrawStar(Context context,AttributeSet attrs){ super(context,attrs); final TypedArray array = context.getTheme().obtainStyledAttributes(attrs,R.styleable.OverWatchLoadingView, 0, 0); mColor = array.getColor(R.styleable.OverWatchLoadingView_view_color, Color.parseColor("#FFCC00")); array.recycle(); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setAlpha(0); mPaint.setColor(mColor); View = this; mScale = 0; initAni(); } public DrawStar(Context context,AttributeSet attrs,int defStyleAttr,Paint mPaint){ super(context,attrs,defStyleAttr); this.mPaint = mPaint; View = this; mScale = 0; initAni(); } public DrawStar(Context context,AttributeSet attrs,int defStyleAttr,int defStyleRes,Paint mPaint){ super(context,attrs,defStyleAttr,defStyleRes); this.mPaint = mPaint; View = this; mScale = 0; initAni(); }
当然,我们需要外部可以控制这些动画的播放,加上几个方法应该就可以了(并没有测试)。
public void pauseLoading() { mShowAni.pause(); } public void continueLoading() { mShowAni.start(); } public void cancelLoading() { mShowAni.cancel(); }
源码传送门(传送门)
相关文章推荐
- [Windows Phone] 自己动手实现Telerik公司的LayoutTransform动画效果
- Script.aculo.us开发系列(四):动画弹出菜单的实现-开发自己的动画
- 自己动手写个ORM 实现(1)
- 自己动手简单实现vbb的URL静态化
- 自己动手实现一个简单的String类
- 自己动手实现自定义线程池
- 在自己的程序中实现OFFICE中的助手动画。
- Flash/Flex学习笔记(36):自己动手实现一个滑块控件(JimmySilder)
- Google首页的图标动画效果,很传神吧?自己也能完美实现,进来请看!!
- 自己动手写个ORM实现(4) 关于反射DataRow数据记录到实体性能的优化
- 自己动手打造ORM(五) —实现
- 自己动手实现AntiForgery。
- 自己动手写个ORM实现(2)
- 练习:自己动手实现一个轻量级的信号量(二)
- 自己动手写控件----textbox之实现视图状态!
- 自己动手实现基于MIDP的ResourceBundle类
- [导入]自己动手,实现jQuery中的ImageCopper.
- [导入]自己动手实现 lucene 搜索代码高亮显示
- 自己动手实现一个简单的string类(二)
- 自己动手,实现在kernel函数中printf()!(转)