先上图,效果大概就是这样,秒针按秒走动,还有两个齿轮不停的旋转
这是一个自定义的View,齿轮是素材,其它的均为画笔画的。
大概的想法是:
1.绘制圆
2.绘制刻度与数字(采用画布的旋转进行绘制比较简单)
3.绘制表针(同样采用画布的旋转实现)
4.绘制齿轮,并实现齿轮的转动
5.齿轮的转动采用属性动画,不停的旋转,表针的动画是在一个线程中,每个1秒,使用postInvalidate() 绘制一遍画布
下面上代码:
package com.example.animation;
import java.util.Calendar;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
public class ClockView extends View{
private Bitmap gbitmap;//那个绿色齿轮
private Bitmap rbitmap;//那个红色齿轮
private Matrix gmatrix;//绿色齿轮的Matrix
private Matrix rmatrix;//红色齿轮的Matrix 齿轮的转动是根据Matrix的setRoate来进行改变的
private Paint paint;
public ClockView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
paint = new Paint();
paint.setAntiAlias(true);
gbitmap = BitmapFactory.decodeResource(getResources(), R.drawable.g_gear);
rbitmap = BitmapFactory.decodeResource(getResources(), R.drawable.r_gear);
gmatrix = new Matrix();
rmatrix = new Matrix();
run();
roate();
}
public void run(){
new Thread(new Runnable() {
@Override
public void run() {
while(true){
postInvalidate();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
//属性动画,是的齿轮旋转
public void roate(){
final ValueAnimator vaAnimator = ValueAnimator.ofFloat(0,1.0f);
vaAnimator.setDuration(3000);
vaAnimator.setInterpolator(new LinearInterpolator());
vaAnimator.setRepeatCount(ValueAnimator.INFINITE);
vaAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float degree = (Float) animation.getAnimatedValue()*360;
gmatrix.setRotate(degree,gbitmap.getWidth()/2,gbitmap.getHeight()/2);//顺时针转动
rmatrix.setRotate(-degree,rbitmap.getWidth()/2,rbitmap.getHeight()/2);//逆时针转动
postInvalidate();
}
});
vaAnimator.start();
}
@Override
protected void onDraw(Canvas canvas) {
gmatrix.postTranslate(getWidth()/2+80, getHeight()/2+160-gbitmap.getHeight()/2);//此处使用postTranslate,和setTranslate可以查看一下
canvas.drawBitmap(gbitmap,gmatrix, null);
rmatrix.postTranslate( getWidth()/2+80-gbitmap.getWidth()-rbitmap.getWidth()/2, getHeight()/2+160-rbitmap.getHeight()/2);
canvas.drawBitmap(rbitmap,rmatrix,null);
// 当前时间对应的角度
Calendar calendar = Calendar.getInstance();
float secRot = calendar.get(Calendar.SECOND) * 6;
float minRot = calendar.get(Calendar.MINUTE) * 6 + 6 * secRot / 360F;
float hrRot = (calendar.get(Calendar.HOUR_OF_DAY) % 12) * 30 + 30 * minRot / 360F;
//绘制圆形表盘
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5.0f);
paint.setColor(Color.BLACK);
canvas.drawCircle(getWidth()/2, getHeight()/2, getWidth()/2, paint);
//绘制刻度
for(int i= 0;i<12;i++){
if(i==0||i==3||i==6||i==9){
paint.setStrokeWidth(5.f);
paint.setTextSize(40);
canvas.drawLine(getWidth()/2, getHeight()/2-getWidth()/2,
getWidth()/2, getHeight()/2-getWidth()/2+60, paint);
String number;
if(i==0){
number = String.valueOf(12);
}else{
number = String.valueOf(i);
}
canvas.drawText(number, getWidth()/2-paint.measureText(number)/2,
getHeight()/2-getWidth()/2+90, paint);
}else{
paint.setStrokeWidth(3.0f);
paint.setTextSize(30);
canvas.drawLine(getWidth()/2, getHeight()/2-getWidth()/2,
getWidth()/2, getHeight()/2-getWidth()/2+60, paint);
String number = String.valueOf(
i);
canvas.drawText(number, getWidth()/2-paint.measureText(number)/2,
getHeight()/2-getWidth()/2+100, paint);
}
//通过使用旋转画布能更轻松的进行绘制
canvas.rotate(30,getWidth()/2,getHeight()/2);
}
//绘制中心圆圈
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(getWidth()/2, getHeight()/2, 10, paint);
//绘制表针
paint.setColor(Color.BLACK);
canvas.translate(getWidth()/2, getHeight()/2);
paint.setStrokeWidth(15);//时针
canvas.rotate(hrRot-90, 0, 0);//旋转绘制
canvas.drawLine(0, 0, 100, 0, paint);
canvas.rotate(-(hrRot-90), 0, 0);//需要将旋转的角度返回,进行下一个正确的绘制
paint.setStrokeWidth(10);//分针
canvas.rotate(minRot-90, 0, 0);
canvas.drawLine(0, 0, 200, 0, paint);
canvas.rotate(-(minRot-90),0,0);
paint.setStrokeWidth(5);
paint.setColor(Color.RED);//秒针
canvas.rotate(secRot-90,0,0);
canvas.drawLine(0, 0, 230, 0, paint);
canvas.rotate(-(secRot-90),0,0);
}
}
布局文件: