对于时钟的这样一个效果控件,一般在开发时候,大多情况为了满足设计师的需要,都是要自定义的,因此,在实现效果之前,需要理清思路,思路很重要,思路清楚了,写代码就轻松很多。
现在我们就先进行时钟分钟秒钟的换算,具体如下:
秒针每转一圈,是360度,那么秒针转一圈分针则转6度,
由此可知秒针每转一秒是6度,秒针每转六度则分针转0.1度,
同理可得秒针每转一秒,时针转动0.008度。
至此理论上的时分秒确定,接下来就是确定自定义View时候的,开始布局了。
自定义View的创建我就不多讲了,直接上核心代码,后面整个项目会上传,需要的可以自行下载。
首先是画一个圆代码如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Log.e("onDraw","onDraw");
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(4);
canvas.drawCircle(width,height,mRadiu,paint);
}
然后开始画刻度,时针,分针,秒针,
刻度时针和分针的画法需要用到一点三角函数的知识,
代码里面有,我就直接上代码了,不写公式了,具体代码如下:
//秒针的坐标
private float startSx;
private float startSy;
private float endSx;
private float endSy;
private float degreeS = 0;
//分针的坐标
private float startMx;
private float startMy;
private float endMx;
private float endMy;
private float degreeM = 0;
//时针的坐标
private float startHx;
private float startHy;
private float endHx;
private float endHy;
private float degreeH = 0;
private boolean isStart;
//秒针线程,控制秒针绘制
new Thread(){
@Override
public void run() {
while (isStart) {
//判断秒针分针时针转满一圈
if (degreeS > 357){
degreeS = 0;
}
if (degreeM>357){
degreeM = 0;
}
if (degreeH>357){
degreeH = 0;
}
//线程是每一秒绘制一次,则每秒增加Math.PI/30度,如果睡眠时间是100,则每秒增加Math.PI/300度,分针和时针同理,也根据线程睡眠时间进行换算就可以了
degreeS += Math.PI/30;
//秒针每转一秒,分针转的角度为0.1度
degreeM += Math.PI/1800;
//秒针每转一秒,时针转动0.008度
degreeH += Math.PI/22500;
postInvalidate();
try {
//通过线程睡眠控制绘图频率
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
for(int i= 0;i<60;i++){
double degree = (Math.PI/30)*i;
//控制始终表格刻度的长度
int length = 10;
switch (i){
case 0:
case 5:
case 10:
case 15:
case 20:
case 25:
case 30:
case 35:
case 40:
case 45:
case 50: length = 20;
}
//计算起始坐标
float startX = (float) (width+(mRadiu*Math.sin(degree)));
float startY = (float) (getHeight()/2-mRadiu+mRadiu*(1-Math.cos(degree)));
//计算结束坐标
float endX = (float) (width+(mRadiu-length)*Math.sin(degree));
float endY = (float) (getHeight()/2-mRadiu+(mRadiu-length)*(1-Math.cos(degree))+length);
// Log.e("circle","mRadiu*Math.sin(i*30) = "+mRadiu*Math.sin(degree)+ " mRadiu*(1-Math.cos(i*3))= "+mRadiu*(1-Math.cos(degree)));
// Log.e("circle","startX = "+startX+ " startY = "+startY);
// Log.e("circle","endX = "+endX+ " endY = "+endY);
canvas.drawLine(startX,startY,endX,endY,paint);
}
//画中心实心黑圆圈
canvas.drawCircle(width,height,10,paint);
//画分针
startMx = (float) (width+((mRadiu-70)*Math.sin(degreeM)));
startMy = (float) (getHeight()/2-(mRadiu-70)*Math.cos(degreeM));
endMx = width;
endMy = height;
paint.setStrokeWidth(8);
paint.setColor(Color.BLACK);
// Log.e("circle","degreeM = "+degreeM+" ((mRadiu-60)*Math.sin(degreeM)) = "+((mRadiu-60)*Math.sin(degreeM))+ " (mRadiu-60)*Math.cos(degreeM)= "+(getHeight()/2-(mRadiu-60)*Math.cos(degreeM)));
canvas.drawLine(startMx,startMy,endMx,endMy,paint);
//画时针
startHx = (float) (width+((mRadiu-90)*Math.sin(degreeH)));
startHy = (float) (getHeight()/2-(mRadiu-90)*Math.cos(degreeH));
endHx = width;
endHy = height;
paint.setStrokeWidth(10);
canvas.drawLine(startHx,startHy,endHx,endHy,paint);
//画秒针
startSx = (float) (width+((mRadiu-50)*Math.sin(degreeS)));
startSy = (float) (getHeight()/2-(mRadiu-50)*Math.cos(degreeS));
// Log.e("circle","degreeS = "+degreeS+" ((mRadiu-50)*Math.sin(degreeS)) = "+((mRadiu-50)*Math.sin(degreeS))+ " (mRadiu-50)*Math.cos(degreeS)= "+(mRadiu-50)*Math.cos(degreeS));
endSx = width;
endSy = height;
paint.setStrokeWidth(5);
paint.setColor(Color.RED);
canvas.drawLine(startSx,startSy,endSx,endSy,paint);
至此,一个基本的自定义时钟就完成了,
效果如下:
还有很多完善空间,比如,在刻度加上时间数,但是由于时间比较紧,就先这样了。