安卓自定义View实现钟表

转载请注明出处:http://blog.csdn.net/baiyuliang2013/article/details/45535227

之前实现过html5版的钟表,html5也有一个画板属性Canvas,相对于安卓的Canvas来说html5的功能要强大的多,就拿钟表的实现,html5要方便简单的多,而安卓实现起来则非常复杂,像指针转动,html5可以画一条线,然后可以用这条线旋转一个弧度即可,而安卓必须是已知起点坐标和终点坐标,这就需要精确计算起始坐标了。先看下效果图,因为是图静态的,动态图也懒得做,所以看个大致效果即可,具体效果可以下载demo观看:

这个钟表并不算完美,正常的钟表,秒针每转动一格,分针和时针都会跟着转动相应的弧度,但本例中偷了个懒,只有秒针转一周时,分针才移动一小格,分针转一周时,时针移动一大格,不满一周的情况下不动,因为画线需要精确的坐标值,如果做到这种效果那工作量可就大了去了,因此我们知道原理即可。

实现思路:

1.重写View,并在ondraw方法中绘图;

2.定义边框宽度,刻度宽度,长度,指针宽度,长度,计算圆心坐标及表盘半径;

3.绘制边框:

mPaint.setStrokeWidth(bordWidth); // 设置圆环的宽度
        mPaint.setColor(bordColor);
		canvas.drawCircle(getWidth()/2, getWidth()/2, r, mPaint);

4.绘制刻度:

//画刻度
		//12
		mPaint.setStrokeWidth(timeLineB_W);
		mPaint.setColor(timeColor);
		canvas.drawLine(circleX,bordWidth, circleX, bordWidth+timeLineB_H, mPaint);
		//12-1
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX+r*Math.cos(Math.toRadians(90-i*6)) ),(float)(circleX-r*Math.cos(Math.toRadians(i*6))), (float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-i*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(i*6))),mPaint);
		}
		//1
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine((float)(circleX+r*Math.cos(Math.toRadians(60)) ),(float)(circleX-r*Math.cos(Math.toRadians(30))), (float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(60))),(float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(30))),mPaint);
		//1-2
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX+r*Math.cos(Math.toRadians(90-30-i*6)) ),(float)(circleX-r*Math.cos(Math.toRadians(30+i*6))), (float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-i*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(30+i*6))),mPaint);
		}
		//2
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine((float)(circleX+r*Math.cos(Math.toRadians(30)) ),(float)(circleX-r*Math.cos(Math.toRadians(60))), (float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(30))),(float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(60))),mPaint);
	   //2-3
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX+r*Math.cos(Math.toRadians(90-60-i*6)) ),(float)(circleX-r*Math.cos(Math.toRadians(60+i*6))), (float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-i*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(60+i*6))),mPaint);
		}
		//3
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine(getWidth()-bordWidth, circleX, getWidth()-bordWidth-timeLineB_H, circleX, mPaint);
		//3-4
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX+r*Math.cos(Math.toRadians(i*6)) ),(float)(circleX+r*Math.cos(Math.toRadians(90-i*6))), (float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(i*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-i*6))),mPaint);
		}
		//4
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine((float)(circleX+r*Math.cos(Math.toRadians(30)) ),(float)(circleX+r*Math.cos(Math.toRadians(60))), (float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(30))),(float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(60))),mPaint);
		//4-5
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX+r*Math.cos(Math.toRadians(30+i*6)) ),(float)(circleX+r*Math.cos(Math.toRadians(90-30-i*6))), (float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(30+i*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-i*6))),mPaint);
		}
		//5
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine((float)(circleX+r*Math.cos(Math.toRadians(60)) ),(float)(circleX+r*Math.cos(Math.toRadians(30))), (float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(60))),(float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(30))),mPaint);
		//5-6
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX+r*Math.cos(Math.toRadians(60+i*6)) ),(float)(circleX+r*Math.cos(Math.toRadians(90-60-i*6))), (float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(60+i*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-i*6))),mPaint);
		}
		//6
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine(circleX,getWidth()-bordWidth, circleX, getWidth()-bordWidth-timeLineB_H,mPaint);

		//6-7
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX-r*Math.cos(Math.toRadians(90-i*6)) ),(float)(circleX+r*Math.cos(Math.toRadians(i*6))), (float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-i*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(i*6))),mPaint);
		}
		//7
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine((float)(circleX-r*Math.cos(Math.toRadians(60)) ),(float)(circleX+r*Math.cos(Math.toRadians(30))), (float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(60))),(float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(30))),mPaint);
		//7-8
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX-r*Math.cos(Math.toRadians(90-30-i*6)) ),(float)(circleX+r*Math.cos(Math.toRadians(30+i*6))), (float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-i*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(30+i*6))),mPaint);
		}
		//8
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine((float)(circleX-r*Math.cos(Math.toRadians(30)) ),(float)(circleX+r*Math.cos(Math.toRadians(60))), (float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(30))),(float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(60))),mPaint);
		//8-9
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX-r*Math.cos(Math.toRadians(90-60-i*6)) ),(float)(circleX+r*Math.cos(Math.toRadians(60+i*6))), (float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-i*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(60+i*6))),mPaint);
		}
		//9
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine(bordWidth,circleX, bordWidth+timeLineB_H, circleX,mPaint);
		//9-10
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX-r*Math.cos(Math.toRadians(i*6)) ),(float)(circleX-r*Math.cos(Math.toRadians(90-i*6))), (float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(i*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-i*6))),mPaint);
		}
		//10
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine((float)(circleX-r*Math.cos(Math.toRadians(30)) ),(float)(circleX-r*Math.cos(Math.toRadians(60))), (float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(30))),(float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(60))),mPaint);
		//10-11
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX-r*Math.cos(Math.toRadians(30+i*6)) ),(float)(circleX-r*Math.cos(Math.toRadians(90-30-i*6))), (float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(30+i*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-i*6))),mPaint);
		}
		//11
		mPaint.setStrokeWidth(timeLineB_W);
		canvas.drawLine((float)(circleX-r*Math.cos(Math.toRadians(60)) ),(float)(circleX-r*Math.cos(Math.toRadians(30))), (float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(60))),(float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(30))),mPaint);
		//11-12
		mPaint.setStrokeWidth(timeLineS_W);
		for(int i=1;i<6;i++){
			canvas.drawLine((float)(circleX-r*Math.cos(Math.toRadians(60+i*6)) ),(float)(circleX-r*Math.cos(Math.toRadians(90-60-i*6))), (float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(60+i*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-i*6))),mPaint);
		}

刻度是逐一计算起始点坐标并绘制的,拿1点的刻度来说,

已知圆心坐标(x,y),半径r,AB长度为a,求A点B点坐标。这应该是初中的题目了吧,很好计算,只要求出A点到y轴和x轴的距离,B点到y轴和x轴的距离即可(最方便的办法就是利用正余玄函数了,而Java也提供了正余玄函数的算法:Math.cos(Math.toRadians(角度值),因为Math.cos传的是弧度,所以要将角度转化为弧度如Math.toRadians(60)),当然要注意屏幕坐标与数学中的象限坐标是不同的,所以AB点坐标要用求出的距离值结合圆的半径求出该点在屏幕中的实际坐标,然后画线即可。

5.绘制指针交点:

mPaint.setStrokeWidth(2);
		mPaint.setStyle(Paint.Style.FILL);
		canvas.drawCircle(circleX,circleX, 10, mPaint);

6.秒针转动:

到这里,我们得思考下,钟表是要动的啊,那怎么实现打开应用钟表就开始走呢?很简单吧,初始化View时,在View的构造方法中开启个线程去不断重绘View即可,时间间隔当然为一秒,这也就给你视觉感是指针一秒转动一次,另外需要你对秒针分针时针转动时相互关联所走的角度有一个清晰的思路,如果你连他们之间的关系都搞不明白,那看代码就更不用说了:

						 while (true){
		                    if (ss == 360){
		                    	mm++;//秒针每转一圈,分针走一格,一格6度,一圈60格
		                    	if(mm==60){
		                    		hh++;//分针转一圈,时针走一格,一格30度,一圈12格
		                    		if(hh==12){
		                    			hh=0;
		                    		}
		                    		mm=0;
		                    	}
		                        ss = 0;
		                    }
		                    	postInvalidate();  //重绘
		                    try{
		                        Thread.sleep(1000);  //暂停1秒
		                    } catch (InterruptedException e){
		                        e.printStackTrace();
		                    }
		                    ss+=6; //360度,分针每秒转动6度
		                }  

秒针转动:

mPaint.setStrokeWidth(timeLineS_W-5);//设置秒针宽度
		mPaint.setColor(pointColor);
		r=r-timeLineB_H-5;//设置秒针长度
		//分针随秒针转动
		if(ss<=30){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-ss*1))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(ss*1))), mPaint);
		}else if(ss<=60){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-(ss-30)*1))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(30+(ss-30)*1))), mPaint);
		}else if(ss<=90){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-(ss-60)*1))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(60+(ss-60)*1))), mPaint);
		}else if(ss<=120){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians((ss-90)*1))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-(ss-90)*1))), mPaint);
		}else if(ss<=150){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(30+(ss-120)*1))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-(ss-120)*1))), mPaint);
		}else if(ss<=180){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(60+(ss-150)*1))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-(ss-150)*1))), mPaint);
		}else if(ss<=210){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-(ss-180)*1))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians((ss-180)*1))), mPaint);
		}else if(ss<=240){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-(ss-210)*1))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(30+(ss-210)*1))), mPaint);
		}else if(ss<=270){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-(ss-240)*1))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(60+(ss-240)*1))), mPaint);
		}else if(ss<=300){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians((ss-270)*1))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-(ss-270)*1))),mPaint);
		}else if(ss<=330){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(30+(ss-300)*1))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-(ss-300)*1))),mPaint);
		}else if(ss<=360){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(60+(ss-330)*1))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-(ss-330)*1))),mPaint);
		}

7.分针转动:

mPaint.setStrokeWidth(timeLineS_W);//设置分针宽度
		r=circleX-bordWidth;//还原
		r=r-timeLineB_H-50;//设置分针长度

		//分针随秒针转动
		if(mm<=5){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-mm*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(mm*6))), mPaint);
		}else if(mm<=10){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-(mm-5)*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(30+(mm-5)*6))), mPaint);
		}else if(mm<=15){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-(mm-10)*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(60+(mm-10)*6))), mPaint);
		}else if(mm<=20){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians((mm-15)*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-(mm-15)*6))), mPaint);
		}else if(mm<=25){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(30+(mm-20)*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-(mm-20)*6))), mPaint);
		}else if(mm<=30){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(60+(mm-25)*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-(mm-25)*6))), mPaint);
		}else if(mm<=35){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-(mm-30)*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians((mm-30)*6))), mPaint);
		}else if(mm<=40){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-(mm-35)*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(30+(mm-35)*6))), mPaint);
		}else if(mm<=45){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-60-(mm-40)*6))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(60+(mm-40)*6))), mPaint);
		}else if(mm<=50){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians((mm-45)*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-(mm-45)*6))),mPaint);
		}else if(mm<=55){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(30+(mm-50)*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-(mm-50)*6))),mPaint);
		}else if(mm<=60){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(60+(mm-55)*6))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-30-(mm-55)*6))),mPaint);
		}

8.时针转动:

r=circleX-bordWidth;//还原
		r=r-timeLineB_H-120;//设置时针长度

		//时针随分针转动
		if(hh<=3){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-hh*30))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(hh*30))), mPaint);
		}else if(hh<=6){
			canvas.drawLine(circleX,circleX,(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians((hh-3)*30))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians(90-(hh-3)*30))), mPaint);
		}else if(hh<=9){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-(hh-6)*30))),(float)(circleX+(r-timeLineS_H)*Math.cos(Math.toRadians((hh-6)*30))), mPaint);
		}else if(hh<=12){
			canvas.drawLine(circleX,circleX,(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians((hh-9)*30))),(float)(circleX-(r-timeLineS_H)*Math.cos(Math.toRadians(90-(hh-9)*30))),mPaint);
		}

9.绘制刻度值:

//写时刻数字
		mPaint.setTextSize(26);
		mPaint.setStrokeWidth(2);
		mPaint.setColor(bordColor);
		canvas.drawText("12", circleX-timeLineB_W, bordWidth+timeLineB_H+30, mPaint);
		canvas.drawText("1", (float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(60)))-20,(float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(30)))+20, mPaint);
		canvas.drawText("2", (float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(30)))-20,(float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(60)))+20, mPaint);
		canvas.drawText("3", getWidth()-bordWidth-timeLineB_H-20, circleX+10, mPaint);
		canvas.drawText("4",(float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(30)))-20,(float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(60))), mPaint);
		canvas.drawText("5", (float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(60)))-15,(float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(30)))-5, mPaint);
		canvas.drawText("6",circleX-10, getWidth()-bordWidth-timeLineB_H-10, mPaint);
		canvas.drawText("7", (float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(60))),(float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(30)))-10, mPaint);
		canvas.drawText("8",  (float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(30)))+10,(float)(circleX+(r-timeLineB_H)*Math.cos(Math.toRadians(60)))+5, mPaint);
		canvas.drawText("9", bordWidth+timeLineB_H+10, circleX+10, mPaint);
		canvas.drawText("10", (float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(30)))+10,(float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(60)))+20, mPaint);
		canvas.drawText("11", (float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(60))),(float)(circleX-(r-timeLineB_H)*Math.cos(Math.toRadians(30)))+25, mPaint);

在做的过程中会发现规律,就是每个大刻度(30度)即12点-1点,1点-2点......这之间所用的代码是相同的,只需要改变一下转动的角度值即可。秒针分为360,一次+6,转动一格为6度;分针分为60,在秒针到360时+1,转动一格为6度;时针分为12,在分针到60时+1,转动一格为30度;这也就是计算的时候有*1的,有*6的,有*30的原因,具体可以体会下代码中的算法,或者你有更好的算法欢迎分享出来!

demo下载地址:http://download.csdn.net/detail/baiyuliang2013/8668103

时间: 2024-12-08 23:32:40

安卓自定义View实现钟表的相关文章

android自定义View之钟表诞生记

很多筒子觉得自定义View是高手的象征,其实不然.大家觉得自定义View难很多情况下可能是因为自定义View涉及到了太多的类和API,把人搞得晕乎乎的,那么今天我们就从最简单的绘图API开始,带大家来一步一步深入自定义View的世界. 先来看看我们今天要实现的一个效果图: 整个效果很简单,就是在屏幕上显示一个钟表,该钟表可以自动走动. OK,那就开始动工吧. 1.准备工作 首先,要实现这个时钟,我得继承自View来自己绘制时钟,因为这种效果没有办法继承已有控件去完善功能.然后我们来看看我们这里需

安卓自定义View文章数据滚动显示数值

本文已经在微信公众号[Android群英传]独家发表. 本文Github代码链接 https://github.com/AndroidMsky/RandomTextView 先看看X金APP的效果: 我们自己实现的效果: 接下来介绍一下我的自定义View RandomTextView的用法和原理 用法 考入 RandomTextView.java 只有200行绝对轻量方便. xml中定义: <com.example.liangmutian.randomtextview.view.RandomTe

安卓自定义View,实时绘图保存为图片

采用单缓冲与双缓冲机制分别实现. 一.单缓冲机制 1.1自定义View,重写ondraw函数 public class Brush extends View { private Paint brush = new Paint(); private Path path = new Path(); int j = 0, n = 0; // xml创建view时调用的构造函数 public Brush(Context context,AttributeSet attrs) { super(contex

安卓自定义View实现图片上传进度显示(仿QQ)

首先看下我们想要实现的效果如下图(qq聊天中发送图片时的效果): 再看下图我们实现的效果: 实现原理很简单,首先我们上传图片时需要一个进度值progress,这个不管是自己写的上传的方法还是使用第三方开源库,其次,需要自定义一个View并重写onDraw方法,此例中的进度是开启了一个线程,然后模仿进度递增,然后将进度值通过自定义View调用一个自定义方法传进自定义View并根据进度进行重绘. 绘制分为三部分: 1.绘制矩形(图片面积)上半部分阴影区: 2.绘制矩形(图片面积)下半部分非阴影区:

安卓自定义 View 进阶:贝塞尔曲线

在上一篇文章Path之基本图形中我们了解了Path的基本使用方法,本次了解Path中非常非常非常重要的内容-贝塞尔曲线. 一.Path常用方法表 为了兼容性(偷懒) 本表格中去除了在API21(即安卓版本5.0)以上才添加的方法.忍不住吐槽一下,为啥看起来有些顺手就能写的重载方法要等到API21才添加上啊.宝宝此刻内心也是崩溃的. 作用相关方法备注 移动起点moveTo移动下一次操作的起点位置 设置终点setLastPoint重置当前path中最后一个点位置,如果在绘制之前调用,效果和moveT

安卓自定义View进阶-Matrix详解

这应该是目前最详细的一篇讲解Matrix的中文文章了,在上一篇文章Matrix原理中,我们对Matrix做了一个简单的了解,偏向理论,在本文中则会详细的讲解Matrix的具体用法,以及与Matrix相关的一些实用技巧. Matrix方法表 按照惯例,先放方法表做概览. 方法类别 相关API 摘要 基本方法 equals hashCode toString toShortString 比较. 获取哈希值. 转换为字符串 数值操作 set reset setValues getValues 设置.

安卓自定义View进阶-Path之玩出花样(PathMeasure)

Path之玩出花样 作者微博: @GcsSloop [本系列相关文章] 可以看到,在经过 Path之基本操作 Path之贝塞尔曲线 和 Path之完结篇(伪) 后, Path中各类方法基本上都讲完了,表格中还没有讲解到到方法就是矩阵变换了,难道本篇终于要讲矩阵了? 非也,矩阵这一部分仍在后面单独讲解,本篇主要讲解 PathMeasure 这个类与 Path 的一些使用技巧. PS:不要问我为什么不讲 PathEffect,因为这个方法在后面的Paint系列中. 先放一个图镇楼,省的下面无聊的内容

安卓自定义View进阶-Matrix原理

Matrix原理 作者微博: @GcsSloop [本系列相关文章] 前言 本文内容偏向理论,和 画布操作 有重叠的部分,本文会让你更加深入的了解其中的原理. 本篇的主角Matrix,是一个一直在后台默默工作的劳动模范,虽然我们所有看到View背后都有着Matrix的功劳,但我们却很少见到它,本篇我们就看看它是何方神圣吧. 由于Google已经对这一部分已经做了很好的封装,所以跳过本部分对实际开发影响并不会太大,不想深究的粗略浏览即可,下一篇中将会详细讲解Matrix的具体用法和技巧. Matr

安卓自定义View进阶 - Path之完结篇(伪)

Path之完结篇(伪) 作者微博: @GcsSloop [本系列相关文章] 经历过前两篇 Path之基本操作 和 Path之贝塞尔曲线 的讲解,本篇终于进入Path的收尾篇,本篇结束后Path的大部分相关方法都已经讲解完了,但Path还有一些更有意思的玩法,应该会在后续的文章中出现吧,嗯,应该会的ˊ_>ˋ 一.Path常用方法表 为了兼容性(偷懒) 本表格中去除了在API21(即安卓版本5.0)以上才添加的方法.忍不住吐槽一下,为啥看起来有些顺手就能写的重载方法要等到API21才添加上啊.宝宝此