绘制1. 创建一个Circle继承自SurfaceView,让surfaceview能够获取canvas,需要实现这个Callback接口,这样在surfaceview准备好了之后才能进行绘制。这里的图是要让圆圈在外面不断的进行绘制,就是蓝色的那个圆圈去动态变化,知道包围整个圆
下面是创建circle类继承自surfaceview并且实现了surfaceview的callback接口
在surfaceview构造方法中设置callback监听为当前surfaceview
实现接口之后先获取surfaceview的宽高,并且调用surfaceview准备好了的接口,这个接口暴露给外面调用者告诉他们surfaceview准备好了可以开始绘制了
接下来看一下绘制线程中绘制圆
线程中有一个绘制circle的方法,在线程run中我们会使用一个while循环一直调用这个方法这样就达到了在圆的外面绘制圆圈的目的。绘制的时候要注意的几点
1. 通过旋转-90度坐标达到圆圈的0度是在竖直向上的方向
2. 前面在获取holder的时候为了让surfaceview本身的黑色背景消失添加的两句代码
3. 绘制文字,文字有上下的通过descent的长度是负数,ascent是正数,descent加上ascent就得到中间a字母的底层那个高度到黄色的baseline的高度,这个计算的长度再除以2就得到字符串的中心了
下面是绘制圆圈的代码
// 绘制圆圈 private void drawCircle() { mListener.onAnimationRunning(Circle.this); Canvas canvas = mHolder.lockCanvas(); if (canvas == null) { return; } canvas.drawRect(0, 0, mWidth, mHeight, mClearPaint); canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); canvas.save(); canvas.scale(0.9f, 0.9f, mWidth * 1f / 2, mHeight * 1f / 2); canvas.drawCircle(mWidth * 1.0f / 2, mHeight * 1.0f / 2, mWidth * 1.0f / 2, mPaint); float centerY = mHeight * 1f / 2; // 这个是获取每个文字的宽度,那么怎么知道有几个文字呢? float ascent = mTextPaint.ascent(); // 正数 float descent = mTextPaint.descent(); // 负数 float textHeight = (ascent + descent) / 2; // float widths[] = new float[2]; // mTextPaint.getTextWidths(TEXT_CIRCLE, widths); canvas.drawText(TEXT_CIRCLE, (float) (mWidth * 0.1)/2, centerY -textHeight, mTextPaint); canvas.restore(); // 旋转坐标画圆圈 canvas.save(); canvas.rotate(-90, mWidth / 2, mHeight / 2); RectF rectF = new RectF((float) (mWidth / 2 * 0.1) / 2, (float) (mWidth / 2 * 0.1) / 2, mWidth - (float) (mWidth / 2 * 0.1) / 2, mHeight - (float) (mWidth / 2 * 0.1) / 2); canvas.drawArc(rectF, 0, mDegree, false, mArcPaint); canvas.restore(); mHolder.unlockCanvasAndPost(canvas); }
在绘图线程的run方法方法中通过循环调用drawcircle来绘制圆圈,用一个标志来判断动画是否结束,在动画开始和结束调用接口的开始和结束方法暴露给外面调用这个view的对象,这样在完成动画之后能够进行其他的动作
下面是动画执行过程的接口, 包括动画的四个阶段,主要在prepared阶段可以调用开始动画的方法,开始动画就是开启一个动画绘制线程并且start即可
开始动画
下面是使用,在layout布局中添加一个circle的控件,然后获取到这个控件并且设置一下动画的监听,在准备好的监听中就可以开始动画了