Android自定义View实现时钟效果

 更新时间:2022年01月12日 08:00:54   作者:仙气儿飘飘w  
这篇文章主要为大家详细介绍了Android自定义View实现时钟效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Android自定义View实现时钟效果的具体代码,供大家参考,具体内容如下

自定义时钟

初学自定义View,先画一个不太成熟的时钟(甚至只有秒针)

时钟效果

@SuppressLint("DrawAllocation")
public class ClockView extends View {

    private final Context mContext;
    private Canvas mCanvas;// 画布
    private Paint clockPaint;// 表盘画笔
    private Paint textPaint;// 文字画笔
    private Paint secondPaint;// 秒针画笔
    private int x,y;// 表中心坐标
    private Thread refreshThread;
    private boolean isStop = false;
    // 用于获取当前秒数
    private  Date currentDate;
    private SimpleDateFormat sp = new SimpleDateFormat("ss");

    @SuppressLint("HandlerLeak")
    private final Handler mHandler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if(msg.what == 0){
                invalidate();//每隔一秒刷新一次
            }
        }
    };

    public ClockView(Context context) {
        this(context,null);
    }

    public ClockView(Context context, @Nullable AttributeSet attrs) {
        this(context,null,0);
    }

    public ClockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context,null,0,0);
    }

    public ClockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        this.mContext = context;
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMeasure;
        // 设置宽高一致
        if(widthMeasureSpec > heightMeasureSpec){
            super.onMeasure(heightMeasureSpec, heightMeasureSpec);
            widthMeasure  = getMeasuredHeight();
        }else{
            super.onMeasure(widthMeasureSpec, widthMeasureSpec);
            widthMeasure = getMeasuredWidth();
        }
        initPaint(widthMeasure);
    }

    private void initPaint(int width){
        // 表盘画笔
        clockPaint = new Paint();
        clockPaint.setColor(mContext.getColor(R.color.black));// 颜色
        clockPaint.setAntiAlias(true);// 抗锯齿
        clockPaint.setStyle(Paint.Style.STROKE);// 样式
        clockPaint.setStrokeWidth(width/80f);// 宽度

        //字体画笔
        textPaint = new Paint();
        textPaint.setColor(mContext.getColor(R.color.black));
        textPaint.setAntiAlias(true);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setTextSize(width/16f);
        textPaint.setTextAlign(Paint.Align.CENTER);

        // 秒针画笔
        secondPaint = new Paint();
        secondPaint.setColor(mContext.getColor(R.color.red));
        secondPaint.setAntiAlias(true);
        secondPaint.setStyle(Paint.Style.FILL);
        secondPaint.setStrokeWidth(5f);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mCanvas = canvas;

        // 获取画布中心坐标
        x = getWidth() / 2;
        y = getHeight() / 2;

        // 绘制表盘
        mCanvas.drawCircle(x, y,getWidth()/40f, clockPaint);// 表盘中心
        mCanvas.drawCircle(x, y, x -getWidth()/40f, clockPaint);// 表盘边框

        // 绘制刻度
        for(int i = 1;i <= 60;i++){
            mCanvas.rotate(6, x, y);
            if(i%5 == 0){
                // 绘制大刻度
                mCanvas.drawLine(x, getWidth()*3/80f, x, getWidth()*5/80f, clockPaint);
            }else{
                // 绘制小刻度
                mCanvas.drawLine(x, getWidth()*3/80f, x, getWidth()/20f, clockPaint);
            }
        }

        // 绘制 1-12小时 字体
        for(int i = 1;i <= 60;i++){
            if(i%5 == 0){
                float x1 = (float) Math.sin(Math.toRadians(6 * i)) * (y * 3 / 4f) + x;
                float y1 = y - (float) Math.cos(Math.toRadians(6 * i)) * (y * 3 / 4f) + getWidth()/40f;
                mCanvas.drawText(String.valueOf(i/5), x1, y1, textPaint);
            }
        }

        // 绘制秒针
        currentDate = new Date(System.currentTimeMillis());
        int ss = Integer.parseInt(sp.format(currentDate));// 获取当前秒数
        // 根据当前秒数 计算出秒针的 start 及 end 坐标
        float sin = (float) Math.sin(Math.toRadians(6 * ss));
        float cos = (float) Math.cos(Math.toRadians(6 * ss));
        float x0 = x - sin * (y / 10f);
        float y0 = y + cos * (y / 10f);
        float x1 = x + sin * (y * 13 / 20f);
        float y1 = y - cos * (y * 13 / 20f);
        mCanvas.drawLine(x0, y0, x1, y1, secondPaint);
        mCanvas.drawCircle(x, y,getWidth()/80f, secondPaint);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        refreshThread = new Thread(){
            @Override
            public void run() {
                super.run();
                while (!isStop){
                    SystemClock.sleep(1000);
                    mHandler.sendEmptyMessage(0);
                }
            }
        };
        refreshThread.start();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mHandler.removeCallbacksAndMessages(null);
        isStop = true;
    }

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

相关文章

  • Android实现Android APP自动更新功能

    Android实现Android APP自动更新功能

    在移动应用的全生命周期中,版本迭代和用户更新体验至关重要,传统的做法是依赖 Google Play 商店强制推送更新,但在某些场景下,我们需要更即时地控制更新流程,所以本文给大家介绍了Android实现Android APP自动更新功能,需要的朋友可以参考下
    2025-04-04
  • Android编程实现ImageView图片抛物线动画效果的方法

    Android编程实现ImageView图片抛物线动画效果的方法

    这篇文章主要介绍了Android编程实现ImageView图片抛物线动画效果的方法,实例分析了Android实现抛物线运动的算法原理与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • android项目手机卫士来电显示号码归属地

    android项目手机卫士来电显示号码归属地

    由于诈骗电话越来越猖狂,号码归属地显示越来越重要,本篇文章主要介绍了android手机卫士来电显示号码归属地,有要的朋友可以了解一下。
    2016-10-10
  • Android短信备份及数据插入实现代码解析

    Android短信备份及数据插入实现代码解析

    这篇文章主要介绍了Android短信备份及数据插入实现代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Android LocationManager获取经度与纬度等地理信息

    Android LocationManager获取经度与纬度等地理信息

    这篇文章主要介绍了Android LocationManager获取经度与纬度等地理信息的相关资料,希望通过本站大家能掌握这样的知识,需要的朋友可以参考下
    2017-09-09
  • Android开启ADB网络调试方法

    Android开启ADB网络调试方法

    今天小编就为大家分享一篇Android开启ADB网络调试方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • Mac Android Studio 3.0 Terminal 中文乱码问题处理

    Mac Android Studio 3.0 Terminal 中文乱码问题处理

    本文给大家分享的是在更新Android Studio 3.0之后,使用Terminal时,发现 git log 命令查看历史 log会乱码,以及最后的解决方法,推荐给小伙伴们
    2017-11-11
  • Android Studio绑定下拉框数据详解

    Android Studio绑定下拉框数据详解

    这篇文章主要为大家详细介绍了Android Studio绑定下拉框数据,Android Studio绑定网络JSON数据,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • 谈谈Android的三种网络通信方式

    谈谈Android的三种网络通信方式

    Android平台有三种网络接口可以使用,他们分别是:java.net.*(标准Java接口)、Org.apache接口和Android.net.*(Android网络接口)。本文详细的介绍,有兴趣的可以了解一下。
    2017-01-01
  • Android进阶事件分发机制解决事件冲突

    Android进阶事件分发机制解决事件冲突

    这篇文章主要为大家介绍了Android进阶事件分发机制解决事件冲突过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01

最新评论