Android指针时钟的实现代码

  1. 最近写了个指针时钟的小程序,拿出来和大家分享一下。
  2. 指针时钟控件实现:
  3. 关键点:
  4. 1、Android自定义控件实现
  5. 2、Android自定义控件命名空间
  6. 3、Android自定义控件从布局文件中获取参数,让自己的控件更具有灵活性、可用性
  7. 4、Android图形绘制(点、线、圆和矩形)
  8. 5、Android Handler消息机制
  9. 主要思想:
  10. 自定义一个控件,继承自View类,实现onMeasuredDimension()方法指定控件大小;实现onDraw()方法计算圆心和偏移角度,来绘制圆心、时针和分针。然后需要做的就是在布局文件中指定钟表背景图、长宽距圆心比例和缩放比例即可。
  11. 一、 实现效果
  12. 二、代码实现
  13. public class HandClockView extends View implements Runnable {
  14. private static final String NAMESPACE = "http://www.pro.dev.com/common";
  15. private static final String CLOCK_FACE="colckFace";
  16. private static final String HAND_CENTER_WIDTH_SCALE = "handCenterWidthScale";
  17. private static final String HAND_CENTER_HEIGHT_SCALE = "handCenterHeightScale";
  18. private static final String SCALE = "scale";
  19. private static final String HOUR_HAND_SIZE = "hourHandSize";
  20. private static final String MINUTE_HAND_SIZE = "minuteHandSize";
  21. private Bitmap clockFace;
  22. private int clockFaceId;
  23. private float centerX;
  24. private float centerY;
  25. private float handCenterWidthScale;
  26. private float handCenterHeightScale;
  27. private float scale;
  28. private int hourHandSize;
  29. private int minuteHandSize;
  30. private Handler handler = new Handler();

 

  1. public HandClockView(Context context) {
  2. super(context);
  3. }
  4. public HandClockView(Context context, AttributeSet attrs) {
  5. super(context, attrs);
  6. init(attrs);
  7. }
  8. public HandClockView(Context context, AttributeSet attrs, int defStyle) {
  9. super(context, attrs, defStyle);
  10. init(attrs);
  11. }
  12. private void init(AttributeSet attrs) {
  13. clockFaceId = attrs.getAttributeResourceValue(NAMESPACE, CLOCK_FACE, 0);
  14. Log.e("zhang.xiao", "clockFaceId=" + clockFaceId);
  15. if (clockFaceId > 0) {
  16. clockFace = BitmapFactory.decodeResource(getResources(), clockFaceId);
  17. }
  18. Log.e("zhang.xiao", "clockFace is null " + String.valueOf(clockFace == null));
  19. handCenterWidthScale = attrs.getAttributeFloatValue(NAMESPACE, HAND_CENTER_WIDTH_SCALE, clockFace.getWidth() / 2);
  20. handCenterHeightScale = attrs.getAttributeFloatValue(NAMESPACE, HAND_CENTER_HEIGHT_SCALE, clockFace.getHeight() / 2);
  21. scale = attrs.getAttributeFloatValue(NAMESPACE, SCALE, 0);
  22. hourHandSize = (int) (scale * attrs.getAttributeIntValue(NAMESPACE, HOUR_HAND_SIZE, 0));
  23. minuteHandSize = (int) (scale * attrs.getAttributeIntValue(NAMESPACE, MINUTE_HAND_SIZE, 0));
  24. }
  25. @Override
  26. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  27. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  28. setMeasuredDimension((int)(clockFace.getWidth() * scale), (int)(clockFace.getHeight() * scale));
  29. }
  30. @Override
  31. public void run() {
  32. invalidate();
  33. handler.postDelayed(this, 60 * 1000);
  34. }
  35. @Override
  36. protected void onDraw(Canvas canvas) {
  37. super.onDraw(canvas);
  38. Paint paint = new Paint();
  39. Rect src = new Rect();
  40. src.left = 0;
  41. src.top = 0;
  42. src.right = clockFace.getWidth();
  43. src.bottom = clockFace.getHeight();
  44. Rect target = new Rect();
  45. target.left = 0;
  46. target.top = 0;
  47. target.right = (int) (src.right * scale);
  48. target.bottom = (int) (src.bottom * scale);
  49. canvas.drawBitmap(clockFace, src, target, paint);
  50. centerX = clockFace.getWidth() * handCenterWidthScale * scale;
  51. centerY = clockFace.getHeight() * handCenterHeightScale * scale;
  52. canvas.drawCircle(centerX, centerY, 5, paint);
  53. paint.setStrokeWidth(3);
  54. Calendar cal = Calendar.getInstance();
  55. int minute = cal.get(Calendar.MINUTE);
  56. int hour = cal.get(Calendar.HOUR);
  57. int second = cal.get(Calendar.SECOND);
  58. Log.e("zhang.xiao", "hour=" + hour);
  59. Log.e("zhang.xiao", "minute=" + minute);
  60. double minuteRadian = Math.toRadians((360 - ((minute * 6) - 90)) % 360);
  61. double hourRadian = Math.toRadians(((360 - ((hour * 30) - 90)) % 360) - (30 * minute / 60));
  62. canvas.drawLine(centerX, centerY, (int) (centerX + minuteHandSize * Math.cos(minuteRadian)),
  63. (int) (centerY - Math.sin(minuteRadian) * minuteHandSize), paint);
  64. paint.setStrokeWidth(4);
  65. canvas.drawLine(centerX, centerY, (int) (centerX + hourHandSize * Math.cos(hourRadian)),
  66. (int) (centerY - Math.sin(hourRadian) * hourHandSize), paint);
  67. handler.postDelayed(this, (60 - second) * 1000);
  68. }
  69. @Override
  70. protected void onDetachedFromWindow() {
  71. super.onDetachedFromWindow();
  72. Log.e("zhang.xiao", "onDetachedFromWindow");
  73.     }
  74. }
  75. 三、
  76. 布局文件中使用<?xml version="1.0" encoding="utf-8"?>
  77. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  78. xmlns:dev="http://www.pro.dev.com/common"
  79.     android:orientation="vertical"
  80.     android:layout_width="fill_parent"
  81.     android:layout_height="fill_parent"
  82.     >
  83. <com.test.HandClockView
  84.   android:layout_width="wrap_content"
  85.   android:layout_height="wrap_content"
  86.   dev:colckFace="@drawable/clock3"
  87.   dev:handCenterWidthScale="0.5"
  88.   dev:handCenterHeightScale="0.5"
  89.   dev:scale="0.3"
  90.   dev:hourHandSize="100"
  91.   dev:minuteHandSize="178"
  92.   >
  93. </com.test.HandClockView>   
  94. </LinearLayout>

标签说明:

dev:自定义控件命名空间

colckFace:钟表背景图

handCenterWidthScale:圆心和图宽缩放比例

handCenterHeightScale:圆心和图片高度缩放比例

scale:图片缩放比例

hourHandSize:时针长度

minuteHandSize:分钟长度 

时钟实现代码二:

前不久在网上看见Android实现的模拟时钟,感觉十分有意思,这里是地址:

极客学院icon-default.png?t=M85Bhttp://www.eoeandroid.com/forum.php?mod=viewthread&tid=58324可惜的是这种方式没有秒表。笔者突然对其有了兴趣,也想去实现以下自己的模拟时钟。折腾了一阵子总算是弄出来了现在将实现方式共享出来,大家一些交流。不多说,先上效果图:

 

 

准备工作

首先我们应该准备相关的素材:时钟盘、时针、分针、秒针图片.

时钟盘:

       

 

时针:

            

 

分针:

           

 

秒针:    

           

 

源码部分

配置文件,比较简单:                    

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical"  
  6.     tools:context=".MainActivity"  
  7.     android:background="@color/bg">  
  8.   
  9.     <com.kiritor.mymodelclock.MyQAnalogClock  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="wrap_content"  
  12.         android:layout_gravity="center"   />  
  13. </LinearLayout>  

       MyQAnalogClock代码:用于构造时钟view以及其刷新显示:

  1. package com.kiritor.mymodelclock;  
  2.   
  3. import android.util.AttributeSet;  
  4. import com.kiritor.mymodelclock.R;  
  5. import android.content.Context;  
  6. import android.graphics.*;  
  7. import android.graphics.drawable.BitmapDrawable;  
  8. import android.os.Handler;  
  9. import android.view.View;  
  10. import java.util.Calendar;  
  11. import java.util.TimeZone;  
  12. /**
  13.  * Created by Kiritor on 13-5-30.
  14.  */  
  15. public class MyQAnalogClock extends View {  
  16.     //时钟盘,分针、秒针、时针对象  
  17.   
  18.     Bitmap mBmpDial;  
  19.     Bitmap mBmpHour;  
  20.     Bitmap mBmpMinute;  
  21.     Bitmap mBmpSecond;  
  22.   
  23.     BitmapDrawable bmdHour;  
  24.     BitmapDrawable bmdMinute;  
  25.     BitmapDrawable bmdSecond;  
  26.     BitmapDrawable bmdDial;  
  27.   
  28.     Paint mPaint;  
  29.   
  30.     Handler tickHandler;  
  31.   
  32.     int mWidth;  
  33.     int mHeigh;  
  34.     int mTempWidth = bmdSecond.getIntrinsicWidth();  
  35.     int mTempHeigh;  
  36.     int centerX;  
  37.     int centerY;  
  38.   
  39.     int availableWidth = 100;  
  40.     int availableHeight = 100;  
  41.   
  42.     private String sTimeZoneString;  
  43.   
  44.   
  45.     public MyQAnalogClock(Context context,AttributeSet attr)  
  46.     {  
  47.        this(context,"GMT+8:00");  
  48.   
  49.     }  
  50.     public MyQAnalogClock(Context context, String sTime_Zone) {  
  51.         super(context);  
  52.         sTimeZoneString = sTime_Zone;  

  1.         mBmpHour = BitmapFactory.decodeResource(getResources(),  
  2.                 R.drawable.shizhen);  
  3.         bmdHour = new BitmapDrawable(mBmpHour);
  4.    
  5.         mBmpMinute = BitmapFactory.decodeResource(getResources(),  

                R.drawable.fenzhen);  

  1.         bmdMinute = new BitmapDrawable(mBmpMinute);
  2.         mBmpSecond = BitmapFactory.decodeResource(getResources(),  
  3.                 R.drawable.miaozhen);  
  4.         bmdSecond = new BitmapDrawable(mBmpSecond);  
  5.   
  6.         mBmpDial = BitmapFactory.decodeResource(getResources(),  
  7.                 R.drawable.android_clock_dial);  
  8.         bmdDial = new BitmapDrawable(mBmpDial);  
  9.         mWidth = mBmpDial.getWidth();  
  10.         mHeigh = mBmpDial.getHeight();  
  11.         centerX = availableWidth / 2;  
  12.         centerY = availableHeight / 2;  
  13.   
  14.         mPaint = new Paint();  
  15.         mPaint.setColor(Color.BLUE);  
  16.         run();  
  17.     }  
  18.   
  19.     public void run() {  
  20.         tickHandler = new Handler();  
  21.         tickHandler.post(tickRunnable);  
  22.     }  
  23.   
  24.     private Runnable tickRunnable = new Runnable() {  
  25.         public void run() {  
  26.             postInvalidate();  
  27.             tickHandler.postDelayed(tickRunnable, 1000);  
  28.         }  
  29.     };  
  30.   
  31.     protected void onDraw(Canvas canvas) {  
  32.         super.onDraw(canvas);  
  33.   
  34.         Calendar cal = Calendar.getInstance(TimeZone  
  35.                 .getTimeZone(sTimeZoneString));  
  36.         int hour = cal.get(Calendar.HOUR);  
  37.         int minute = cal.get(Calendar.MINUTE);  
  38.         int second = cal.get(Calendar.SECOND);  
  39.         float hourRotate = hour * 30.0f + minute / 60.0f * 30.0f;  
  40.         float minuteRotate = minute * 6.0f;  
  41.         float secondRotate = second * 6.0f;  
  42.   
  43.         boolean scaled = false;  
  44.   
  45.         if (availableWidth < mWidth || availableHeight < mHeigh) {  
  46.             scaled = true;  
  47.             float scale = Math.min((float) availableWidth / (float) mWidth,  
  48.                     (float) availableHeight / (float) mHeigh);  
  49.             canvas.save();  
  50.             canvas.scale(scale, scale, centerX, centerY);  
  51.         }  
  52.   
  53.         bmdDial.setBounds(centerX - (mWidth / 2), centerY - (mHeigh / 2),  
  54.                 centerX + (mWidth / 2), centerY + (mHeigh / 2));  
  55.         bmdDial.draw(canvas);  
  56.   
  57.         mTempWidth = bmdHour.getIntrinsicWidth();  
  58.         mTempHeigh = bmdHour.getIntrinsicHeight();  
  59.         canvas.save();  
  60.         canvas.rotate(hourRotate, centerX, centerY);  
  61.         bmdHour.setBounds(centerX - (mTempWidth / 2), centerY  
  62.                 - (mTempHeigh / 2), centerX + (mTempWidth / 2), centerY  
  63.                 + (mTempHeigh / 2));  
  64.         bmdHour.draw(canvas);  
  65.   
  66.         canvas.restore();  
  67.   
  68.         mTempWidth = bmdMinute.getIntrinsicWidth();  
  69.         mTempHeigh = bmdMinute.getIntrinsicHeight();  
  70.         canvas.save();  
  71.         canvas.rotate(minuteRotate, centerX, centerY);  
  72.         bmdMinute.setBounds(centerX - (mTempWidth / 2), centerY  
  73.                 - (mTempHeigh / 2), centerX + (mTempWidth / 2), centerY  
  74.                 + (mTempHeigh / 2));  
  75.         bmdMinute.draw(canvas);  
  76.   
  77.         canvas.restore();  
  78.   
  79.         mTempWidth = bmdSecond.getIntrinsicWidth();  
  80.         mTempHeigh = bmdSecond.getIntrinsicHeight();  
  81.         canvas.rotate(secondRotate, centerX, centerY);  
  82.         bmdSecond.setBounds(centerX - (mTempWidth / 2), centerY  
  83.                 - (mTempHeigh / 2), centerX + (mTempWidth / 2), centerY  
  84.                 + (mTempHeigh / 2));  
  85.         bmdSecond.draw(canvas);  
  86.   
  87.         if (scaled) {  
  88.             canvas.restore();  
  89.         }  
  90.     }  
  91. }  

     主Activity:

  1. package com.kiritor.mymodelclock;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5.   
  6. /**
  7.  * Created by Kiritor on 13-5-30.
  8.  */  
  9. public class MainActivity extends Activity {  
  10.     public void onCreate(Bundle savedInstanceState) {  
  11.         super.onCreate(savedInstanceState);  
  12.         setContentView(R.layout.activity_main);  
  13.     }  
  14. }  

好了一个简单的模拟时钟就完成了,不过通过观察运行效果可以看出的是,笔者对           时针、分针、秒针图片的设计不是太美观,看的不是太清楚,体验略差。不过这不是重点读者可以自己去设计一下那4张图片,从而做出不同的效果!这里本实例使用Android Studio做的,完整项目源码就不上传了!Over!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bryan Ding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值