服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android自定义控件实现时钟效果

Android自定义控件实现时钟效果

2022-11-11 15:57lizonghuan Android

这篇文章主要介绍了Android自定义控件实现时钟效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

在学习安卓群英传自定义控件章节的时候,有一个例子是绘制时钟,在实现了书上的例子后就想看这个时钟能不能动起来。

这里选择延迟一秒发送消息重绘view来实现的动画,对外提供了开启时钟,关闭时钟的方法,当activity执行onResume方法的时候,执行startClock()方法,当移除view或activity执行onStop方法的时候可以执行stopClock()方法。

首先根据view的宽高来确定圆心的位置,并画出一个圆。再通过view高度的一半减去圆的半径,确定刻度的起始位置,选择刻度的长度并绘制出来。然后再刻度下方绘制出数字。最终将画布进行旋转,时钟总共有60个刻度,循环旋转,每次旋转6度即可。

最后是绘制指针,通过计算算出指针对应每个刻度的X,Y坐标并绘制直线。

Android自定义控件实现时钟效果

代码实现

自定义控件的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
public class ClockView extends View{
 private Paint circlePaint,dialPaint,numberPaint;
 //view 的宽高
 private float mWidth,mHeight;
 //圆的半径
 private float circleRadius;
 //圆心X,Y坐标
 private float circleX,circleY;
 private int second,minute;
 private double hour;
 
 private Handler handler = new Handler(Looper.getMainLooper()){
  @Override
  public void handleMessage(Message msg) {
   super.handleMessage(msg);
   if(msg.what==0){
    invalidate();
   }
  }
 };
 
 public ClockView(Context context, AttributeSet attrs) {
  super(context, attrs);
  initPaint();
 }
 
 private void initPaint(){
  //刻盘圆,小时刻度,时针和分针的画笔
  circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  circlePaint.setColor(Color.BLACK);
  circlePaint.setStyle(Paint.Style.STROKE);
  circlePaint.setStrokeWidth(10);
 
  //分钟刻度的画笔
  dialPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  dialPaint.setColor(Color.BLACK);
  dialPaint.setStrokeWidth(5);
 
  //数字的画笔
  numberPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  numberPaint.setColor(Color.BLACK);
  numberPaint.setStrokeWidth(5);
  numberPaint.setTextSize(30);
 }
 
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  mWidth = getMeasuredWidth();
  mHeight = getMeasuredHeight();
  if(mWidth<mHeight){
   //圆的半径为view的宽度的一半再减9,防止贴边
   circleRadius = mWidth/2-9;
   circleX = mWidth/2;
   circleY = mHeight/2;
  } else{
   circleRadius = mHeight/2-9;
   circleX = mWidth/2;
   circleY = mHeight/2;
  }
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  setTimes();
  drawCirclePoint(canvas);
  drawCircle(canvas);
  drawDial(canvas);
  drawPointer(canvas);
 }
 
 /**圆心
  * @param canvas
  */
 private void drawCirclePoint(Canvas canvas){
  canvas.drawCircle(circleX,circleY,5,circlePaint);
 }
 
 private void drawCircle(Canvas canvas){
  canvas.drawCircle(circleX,circleY,circleRadius,circlePaint);
 }
 
 /**画刻度及时间
  * @param canvas
  */
 private void drawDial(Canvas canvas){
  //时钟用长一点的刻度,画笔用画圆的画笔
  Point hourStartPoint = new Point(circleX,circleY-circleRadius);
  Point hourEndPoint = new Point(circleX,circleY-circleRadius+40);
  //分钟的刻度要稍微短一些,画笔用画圆的画笔
  Point startPoint2 = new Point(circleX,circleY-circleRadius);
  Point endPoint2 = new Point(circleX,circleY-circleRadius+10);
  //开始画刻度和数字,总共60个刻度,12个时钟刻度,被5整除画一个时钟刻度,被其余的为分针刻度
  String clockNumber;
  for(int i=0;i<60;i++){
   if(i%5==0){
    if(i==0){
     clockNumber = "12";
    } else{
     clockNumber = String.valueOf(i/5);
    }
    //时针刻度
    canvas.drawLine(hourStartPoint.getX(),hourStartPoint.getY(),hourEndPoint.getX(),hourEndPoint.getY(),circlePaint);
    //画数字,需在时针刻度末端加30
    canvas.drawText(clockNumber,circleX-numberPaint.measureText(clockNumber)/2,hourEndPoint.getY()+30,numberPaint);
   } else{
    //画分针刻度
    canvas.drawLine(startPoint2.getX(),startPoint2.getY(),endPoint2.getX(),endPoint2.getY(),circlePaint);
   }
   //画布旋转6度
   canvas.rotate(360/60,circleX,circleY);
  }
 }
 
 /**画指针
  * X点坐标 cos(弧度)*r
  * Y点坐标 sin(弧度)*r
  * toRadians将角度转成弧度
  * 安卓坐标系与数学坐标系不同的地方是X轴是相反的,所以为了调整方向,需要将角度+270度
  * @param canvas
  */
 private void drawPointer(Canvas canvas){
  canvas.translate(circleX,circleY);
  float hourX = (float) Math.cos(Math.toRadians(hour*30+270))*circleRadius*0.5f;
  float hourY = (float) Math.sin(Math.toRadians(hour*30+270))*circleRadius*0.5f;
  float minuteX = (float) Math.cos(Math.toRadians(minute*6+270))*circleRadius*0.8f;
  float minuteY = (float) Math.sin(Math.toRadians(minute*6+270))*circleRadius*0.8f;
  float secondX = (float) Math.cos(Math.toRadians(second*6+270))*circleRadius*0.8f;
  float secondY = (float) Math.sin(Math.toRadians(second*6+270))*circleRadius*0.8f;
  canvas.drawLine(0,0,hourX,hourY,circlePaint);
  canvas.drawLine(0,0,minuteX,minuteY,circlePaint);
  canvas.drawLine(0,0,secondX,secondY,dialPaint);
  //一秒重绘一次
  handler.sendEmptyMessageDelayed(0,1000);
 }
 
 public void startClock(){
  setTimes();
  invalidate();
 }
 
 private void setTimes(){
  Date date = new Date();
  Calendar calendar = Calendar.getInstance();
  calendar.setTime(date);
  second = getTimes(date,Calendar.SECOND);
  minute = getTimes(date,Calendar.MINUTE);
  hour = getTimes(date,Calendar.HOUR)+minute/12*0.2;
 }
 
 private int getTimes(Date date,int calendarField){
  Calendar calendar = Calendar.getInstance();
  calendar.setTime(date);
  return calendar.get(calendarField);
 }
 
 public void stopClock(){
  handler.removeMessages(0);
 }
}

public class Point {
private float x;
private float y;

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public Point(float x, float y) {
 this.x = x;
 this.y = y;
}
 
public float getX() {
 return x;
}
 
public void setX(float x) {
 this.x = x;
}
 
public float getY() {
 return y;
}
 
public void setY(float y) {
 this.y = y;
}

Acitivity:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ClockActivity extends Activity{
 
  private ClockView clockView;
 
  @Override
  protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.clock_layout);
   clockView = (ClockView) findViewById(R.id.clock);
  }
 
  @Override
  protected void onResume() {
   super.onResume();
   clockView.startClock();
  }
 
  @Override
  protected void onStop() {
   super.onStop();
   clockView.stopClock();
  }
 }

xml布局:

?
1
2
3
4
5
6
7
8
9
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical" android:layout_width="match_parent"
 android:gravity="center"
 android:layout_height="match_parent">
 <com.example.customview.view.ClockView
  android:layout_width="match_parent"
  android:id="@+id/clock"
  android:layout_height="match_parent" />
</LinearLayout>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/lizonghuan/article/details/52184611

延伸 · 阅读

精彩推荐