自定义View-自制简单的钟表

先上图,效果大概就是这样,秒针按秒走动,还有两个齿轮不停的旋转

自定义View-自制简单的钟表_第1张图片

这是一个自定义的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);
	}
	
}

至于那两个齿轮,我是在easyicon上找的,进去搜索齿轮就有...

布局文件:



    



OK,有错误的地方请指出..


你可能感兴趣的:(android)