安卓自定义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
安卓自定义View实现钟表的更多相关文章
- 安卓自定义View教程目录
基础篇 安卓自定义View基础 - 坐标系 安卓自定义View基础 - 角度弧度 安卓自定义View基础 - 颜色 进阶篇 安卓自定义View进阶 - 分类和流程 安卓自定义View进阶 - Canv ...
- 安卓自定义View进阶-Canvas之画布操作 转载
安卓自定义View进阶-Canvas之画布操作 转载 https://www.gcssloop.com/customview/Canvas_Convert 本来想把画布操作放到后面部分的,但是发现很多 ...
- android自定义View之钟表诞生记
很多筒子觉得自定义View是高手的象征,其实不然.大家觉得自定义View难很多情况下可能是因为自定义View涉及到了太多的类和API,把人搞得晕乎乎的,那么今天我们就从最简单的绘图API开始,带大家来 ...
- 安卓自定义View(一)自定义控件属性
自定义View增加属性第一步:定义属性资源文件 在/res/values 文件夹下建立"Values XML layout",按照如下定义一个textview的属性 <?xm ...
- 安卓自定义View实现图片上传进度显示(仿QQ)
首先看下我们想要实现的效果如下图(qq聊天中发送图片时的效果): 再看下图我们实现的效果: 实现原理很简单,首先我们上传图片时需要一个进度值progress,这个不管是自己写的上传的方法还是使用第三方 ...
- 安卓自定义View实例-----跟随手指移动的鸟
今天学习了一些安卓开发中的自定义布局,编写了简单一个实例,“跟随手指移动的鸟”,需要两张图片,背景图片和鸟的图片,鸟的图片可以在屏幕中跟随手指的移动而移动. 1.将两张图片导入到mipmap中: 2. ...
- 安卓自定义View基础 --坐标系,角度弧度,颜色
转自:https://www.gcssloop.com/customview/CustomViewIndex/ 1.坐标系 2.角度弧度 3.颜色 一.屏幕坐标系和数学坐标系的区别 由于移动设备一般定 ...
- Android 自定义View合集
自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...
- Android自定义View之ProgressBar出场记
关于自定义View,我们前面已经有三篇文章在介绍了,如果筒子们还没阅读,建议先看一下,分别是android自定义View之钟表诞生记.android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检 ...
随机推荐
- bzoj 5289: [Hnoi2018]排列
Description Solution 首先注意到实际上约束关系构成了一棵树 考虑这个排列 \(p\),编号为 \(a[i]\) 的出现了,\(i\) 才可以出现 那么如果连边 \((a[i],i) ...
- 【Codeforces AIM Tech Round 4 (Div. 2) C】
·将排序限制于子序列中,又可以说明什么呢? C. Sorting by Subsequences ·英文题,述大意: 输入一个长度为n的无重复元素的序列{a1,a2……an}(1<= ...
- 【vijos1943】上学路上
题目戳这里 描述 小雪与小可可吵架了,他们决定以后互相再也不理对方了.尤其是,他们希望以后上学的路上不会再相遇. 我们将他们所在城市的道路网视作无限大的正交网格图,每一个整数点 (x,y) 对应了一个 ...
- 在 telnet 中利用HTTP协议传递GET、POST参数
HTTP协议不仅可以用在浏览器中,还可以用在任何支持它的地方,平时用浏览器访问网站时HTTP协议内容是隐藏起来看不到的,用 telnet 就能揭开它的神秘面纱.telnet 开启方法参考文章末尾——t ...
- 如何在Google上下载高清原图
在我们学习和生活中常常一些高清图片作为相关的素材,比如制作PPT.写博文.制作视频都需要大量图片.我们常常会在百度上下载一些图片,但是百度上提供的图片存在很多问题:存在水印.清晰度不够等.而Googl ...
- python四则运算
源代码已上传至Github,https://github.com/chaigee/arithmetic,中的python_ari.py文件 题目: (1)能自动生成小学四则运算题目,并且不能出现负数: ...
- AnyConnect使用说明(手机版)
一.下载安装客户端 iPhone手机在App Store 里搜索 “Anyconnect”下载安装. Android手机需另外下载Anyconnect. 二. 1.打开AnyConnect,点击&qu ...
- swing JTable 更新数据
rowData 是将要更新的表格内数据,coloumnName是将要更新的表头数据. table是原本的table对象,更新数据的时候要用 DefaultTableModel 类~ /*更新table ...
- Node.js UDP/Datagram
稳定性: 3 - 稳定 调用 require('dgram') ,可以使用数据报文 sockets(Datagram sockets). 重要提醒: dgram.Socket#bind() 的行为在 ...
- Docker命令查询
基本语法 docker [OPTIONS] COMMAND [arg...] 一般来说,Docker 命令可以用来管理 daemon,或者通过 CLI 命令管理镜像和容器.可以通过 man docke ...