Recently, I implemented a function in android. I drew a simulated hour hand in the activity and touched the hour hand and minute hand to adjust the time.
In fact, it was quite simple to start with, but it took me nearly a week to implement it all...
1. Draw a clock in the activity. Sometimes the needle is followed by a split needle and the code is omitted.
The dial, hour hand, and minute hand are both imageView. a bitmap is created and the imageView of the minute hand is built on it. The bitmap rotates to a certain angle. At this time, the angle of the hour hand is displayed.
2. Add an onTouch event to the sub-needle:
Since imageView is covered by a layer, the imageView in my code is located at the top, so all my touch events are written on the needle;
Basic principle: When I touch mImageView_minuteHand with my finger, there will be a coordinate of the point, based on the coordinate of the point to determine the position of the point, is a simulated clock interface:
I divide the clock into four quadrant, 0-15 minutes for the First quadrant, 15-30 minutes for the second quadrant, 30-45 minutes for the third quadrant, 45-60 minutes for the Fourth quadrant, these four parts are mainly prepared for the following calculation perspectives.
0 points are 0 degrees, and the o point is the center. As a result, when my hand points to a certain position in the disc, there is a straight line connecting to the center of the circle, there is also a straight line between the center of the circle and the zero point, and the angle between the two straight lines can be calculated. However, because the slope of the straight line connecting the center and the zero point does not exist, so I replaced it with a line between the center and 15 points, as shown in the red line in the figure.
Calculate the angle code of the two straight lines:
[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 and startY are the 15 points in the graph, centerX and centerY are the center point o points in the graph, and endX and endY are the points my fingers point, next, calculate the line between the point where my finger is located and the center of the circle and the angle between 0 degrees:
[Java]
If (endY <width/2 & endX> width/2) {// In the first quadrant
FirstTouchDegree = 90-tmpDegree;
System. out. println ("firstTouchDegree <90..." + firstTouchDegree );
} Else if (endY> width/2 & endX> width/2) {// located in the second quadrant
FirstTouchDegree = 90 + tmpDegree;
System. out. println ("firstTouchDegree90-180..." + firstTouchDegree );
} Else if (endY> width/2 & endX <width/2) {// In the third quadrant
FirstTouchDegree = 270-tmpDegree;
System. out. println ("firstTouchDegree180-270..." + firstTouchDegree );
} Else if (endX <width/2 & endY <width/2) {// located in the Fourth quadrant
FirstTouchDegree = 180 + 90 + tmpDegree;
System. out. println ("firstTouchDegree> 270..." + firstTouchDegree );
} Else if (endX = width/2 & endY <width/2) {// The value is at 0.
FirstTouchDegree = 0.0;
} Else if (endX = width/2 & endY> width/2) {// at 30 minutes
FirstTouchDegree = 180.0;
}
If (endY <width/2 & endX> width/2) {// In the first quadrant
FirstTouchDegree = 90-tmpDegree;
System. out. println ("firstTouchDegree <90..." + firstTouchDegree );
} Else if (endY> width/2 & endX> width/2) {// located in the second quadrant
FirstTouchDegree = 90 + tmpDegree;
System. out. println ("firstTouchDegree90-180..." + firstTouchDegree );
} Else if (endY> width/2 & endX <width/2) {// In the third quadrant
FirstTouchDegree = 270-tmpDegree;
System. out. println ("firstTouchDegree180-270..." + firstTouchDegree );
} Else if (endX <width/2 & endY <width/2) {// located in the Fourth quadrant
FirstTouchDegree = 180 + 90 + tmpDegree;
System. out. println ("firstTouchDegree> 270..." + firstTouchDegree );
} Else if (endX = width/2 & endY <width/2) {// The value is at 0.
FirstTouchDegree = 0.0;
} Else if (endX = width/2 & endY> width/2) {// at 30 minutes
FirstTouchDegree = 180.0;
} In the above Code, firstTouchDegree is the angle between the current position of my finger and the degree of 0. As mentioned above, my imageView is stacked layer by layer, therefore, I can only touch the top-level imageView. In this example, It is mImageView_minuteHand. Therefore, I want to determine whether the position I clicked is the hour hand or the minute hand, but if the hour hand and the minute hand overlap, so when I click this position, it must be the minute hand instead of the hour hand...
The angle between the hour hand and the minute hand can be determined at the beginning. The circle is 360 degrees, so I have 6 ° for a minute and 30 ° for an hour. If the number of minutes is not 0, the hour hand angle is hour * 30 + minute * 0.5;
After getting the angle between the hour hand and the minute hand, we can determine that If I clicked near the hour hand, then I will let the hour hand rotate when I turned the position of my finger, if the position is near the minute hand, the split needle is rotating.
The bottom layer of the layer is a layer of scrollView, so when I detect onTouchListener, I want to stop the rotation of my parent view:
[Java]
V. getParent (). requestDisallowInterceptTouchEvent (true );
V. getParent (). requestDisallowInterceptTouchEvent (true); then, rotate the image based on the position where my fingers rotate.
PS: I wrote the touch events of the hour hand and the minute hand together, but simply determined which pointer to be rotated based on the position of my finger, instead of setting an event for each pointer, I always think there is something wrong ....