Android_模拟时钟内时针、分针触摸转动
最近实现了android里的一个机能,在activity里面画了一个模拟的时针,然后触摸上面的时针跟分针可以实现调时间的功能。
其实,说起原来来还是挺简单的,但是我花了将近一周的时间才全部实现,有点惭愧。。。
一、在activity里面画一个时钟,有时针跟分针,代码略。
表盘、时针和分针都是imageView,创建一个位图,然后上面盖了分针的imageView,位图旋转一定的角度,这个时候显示的就是时针的角度。
二、给分针添加onTouch事件:
由于imageView是一层盖着一层的,所以我的代码里是分针的imageView在最上面,所以我的触摸事件就全部写在分针上;
基本原理:当我的手指触摸到mImageView_minuteHand的时候,会有个点坐标,根据点的坐标来判断我点的位置,下图是模拟的时钟界面:
我把时钟分为四个象限,0-15分钟为第一象限,15-30分钟为第二象限,30-45分钟为第三象限,45-60分钟为第四象限,分这四块主要是为了下面的计算角度准备的。
0分的时候为0度,以o点为中心,这样一来我手在圆盘里点到某个位置的时候,连接圆心就有一条直线,圆心与0分连接也有一条直线,就可以计算两条直线的夹角了,但是由于圆心与0分连接的直线斜率不存在,所以我用圆心与15分的连线代替,图中红线所示。
计算两条直线的夹角代码:
[java]
double k1 = (double)(startY - centerY)/(startX - centerX);
double k2 = (double)(endY - centerY)/(endX - centerX);
double tmpDegree = Math.atan((Math.abs(k1 - k2))/(1 + k1*k2)) / Math.PI * 180 ;
double k1 = (double)(startY - centerY)/(startX - centerX);
double k2 = (double)(endY - centerY)/(endX - centerX);
double tmpDegree = Math.atan((Math.abs(k1 - k2))/(1 + k1*k2)) / Math.PI * 180 ;startX与startY为图中的15分所在点,centerX与centerY为图中的中心点o点,endX与endY就是我手指所点的点,接下来就是计算我手指所在的点与圆心的连线和0度的夹角:
[java]
if(endY < width/2 && endX > width/2){ //位于第一象限
firstTouchDegree = 90 - tmpDegree;
System.out.println("firstTouchDegree<90..."+ firstTouchDegree);
}else if (endY > width/2 && endX > width/2 ) { //位于第二象限
firstTouchDegree = 90 + tmpDegree;
System.out.println("firstTouchDegree90-180..."+ firstTouchDegree);
}else if (endY > width/2 && endX < width/2 ) { //位于第三象限
firstTouchDegree = 270 - tmpDegree;
System.out.println("firstTouchDegree180-270..."+ firstTouchDegree);
}else if (endX < width/2 && endY < width/2) { //位于第四象限
firstTouchDegree = 180 + 90 + tmpDegree;
System.out.println("firstTouchDegree>270..."+ firstTouchDegree);
}else if (endX == width/2 && endY < width/2) { //位于0分位置
firstTouchDegree = 0.0;
}else if (endX == width/2 && endY > width/2) { //位于30分位置
firstTouchDegree = 180.0;
}
if(endY < width/2 && endX > width/2){ //位于第一象限
firstTouchDegree = 90 - tmpDegree;
System.out.println("firstTouchDegree<90..."+ firstTouchDegree);
}else if (endY > width/2 && endX > width/2 ) { //位于第二象限
firstTouchDegree = 90 + tmpDegree;
System.out.println("firstTouchDegree90-180..."+ firstTouchDegree);
}else if (endY > width/2 && endX < width/2 ) { //位于第三象限
firstTouchDegree = 270 - tmpDegree;
System.out.println("firstTouchDegree180-270..."+ firstTouchDegree);
}else if (endX < width/2 && endY < width/2) { //位于第四象限
firstTouchDegree = 180 + 90 + tmpDegree;
System.out.println("firstTouchDegree>270..."+ firstTouchDegree);
}else if (endX == width/2 && endY < width/2) { //位于0分位置
firstTouchDegree = 0.0;
}else if (endX == width/2 && endY > width/2) { //位于30分位置
firstTouchDegree = 180.0;
}上述代码中的firstTouchDegree是我手指当前点下去的位置与0度的夹角,上面也提到了,我的imageView都是一层层的叠在一起的,所以我只能触摸到最上层的imageView,本例中是mImageView_minuteHand,所以接下来我就是要判断我点的位置是时针还是分针,但是如果时针跟分针重合在一块的话,那么我点这个位置的时候动的肯定就是分针而不是时针。。。
时针和分针的角度一开始是可以确定的,一个圆是360度,所以我一分钟就是6°,一个小时是30°;如果分钟数不为0,那么时针的角度就是hour * 30 + minute * 0.5;
得到了时针和分针的角度以后,就可以判断如果我点的是时针附近,那么我转动我手指位置的时候就让时针旋转,如果位置在分针附近,那么旋转的时候就是分针在旋转。
在图层的最底层是一层scrollView,所以当我检测到onTouchListener的时候,我要让我的父view停止转动:
[java]
v.getParent().requestDisallowInterceptTouchEvent(true);
v.getParent().requestDisallowInterceptTouchEvent(true);然后就是根据我手指转动的位置来旋转我的图片即可。
PS:本人把时针跟分针的触摸事件都写在一起去了,只是单纯的根据我手指的位置来判断转动哪个指针,而不是给每个指针写定了某个事件,总觉得有些不妥。。。。
补充:移动开发 , Android ,