自定义时钟View,表盘的绘制

实现的效果图如下:

 main中布局文件:

 <com.example.drawtime.MyClock
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

values文件夹下新建一个xml文件,定义参数

<resources>
    <declare-styleable name="MyView">
        <attr name="MyView_color" format="color"/>
        <attr name="MyView_radius" format="float"/>
    </declare-styleable>
</resources>

1.自定义一个类 MyClock extends View,并设置统一的入口

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

    public MyClock(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyClock(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyView, defStyleAttr, 0);
        //获得xml属性
        color = typedArray.getColor(R.styleable.MyView_MyView_color, CIRCLE_CLOCK);
        radius = typedArray.getFloat(R.styleable.MyView_MyView_radius, CIRCLE_RADIUS);
        typedArray.recycle();
    }
2.测量控件的宽高

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    }

    private int measureHeight(int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            heightResult = size;
        } else {
            heightResult = 600;
            if (mode == MeasureSpec.AT_MOST) {
                heightResult = Math.min(heightResult, size);
            }
        }
        return heightResult;
    }

    private int measureWidth(int widthMeasureSpec) {
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int size = MeasureSpec.getSize(widthMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            widthResult = size;
        } else {
            widthResult = 600;//给一个默认的宽度
            if (mode == MeasureSpec.AT_MOST) {
                widthResult = Math.min(widthResult, size);
            }
        }
        return widthResult;
    }
3.----------------------现在就要开始绘制了---------------------------

我把他们封装为方法

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制表盘
        BiaoPan(canvas);
        //绘制logo
        Logo(canvas);
        //绘制数字时间
        Time(canvas);
        //画刻度
        drgree(canvas);
        //画表盘时间数字
        HourText(canvas);

        mHandler.sendEmptyMessage(HANDLER_MSG);

        //画时针
        canvas.save();
        hour(canvas);
        canvas.restore();
        //画分针
        canvas.save();
        minutes(canvas);
        canvas.restore();
        //画秒针
        canvas.save();
        second(canvas);
        canvas.restore();
        //画中间小点
        Point(canvas);
    }
3.1绘制表盘

private void BiaoPan(Canvas canvas) {
        mBiaoPan = new Paint();
        mBiaoPan.setAntiAlias(true);
        canvas.translate(widthResult / 2, heightResult / 2);
        mBiaoPan.setStyle(Paint.Style.STROKE);
        mBiaoPan.setColor(color);
        mBiaoPan.setStrokeWidth(2);
        canvas.drawCircle(0, 0, radius, mBiaoPan);
    }
3.2绘制Logo,正负代表方向

private void Logo(Canvas canvas) {

        mLogoPaint = new TextPaint();
        mLogoPaint.setColor(Color.parseColor("#FF4081"));
        mLogoPaint.setAntiAlias(true);
        mLogoPaint.setStyle(Paint.Style.STROKE);
        mLogoPaint.setStrokeWidth(2);
        mLogoPaint.setTextSize(50);
        float textwith = mLogoPaint.measureText(BIAO_LOGO);
        canvas.drawText(BIAO_LOGO, -textwith / 2, -radius / 5 * 2, mLogoPaint);

    }
3.3绘制数字的时间,默认 00:00:00

private void Time(Canvas canvas) {

        mTimePaint = new Paint();
        mTimePaint.setAntiAlias(true);
        mTimePaint.setColor(Color.GREEN);
        mTimePaint.setStyle(Paint.Style.FILL);
        mTimePaint.setTextSize(45);
        /**根据实际情况我们需要判断下时分秒的数字是不是小于10,如果是前面补一位0*/
        if (mSecond < 10) {
            replaceMsecond = "0" + String.valueOf(mSecond).replace(".0", "");
        } else {
            replaceMsecond = String.valueOf(mSecond).replace(".0", "");
        }
        if (mMinutes < 10) {
            replaceMminutes = "0" + String.valueOf(mMinutes).replace(".0", "");
        } else {
            replaceMminutes = String.valueOf(mMinutes).replace(".0", "");
        }
        if (mHour < 10) {
            replaceMhour = "0" + String.valueOf(mHour).replace(".0", "");
        } else {
            replaceMhour = String.valueOf(mHour).replace(".0", "");
        }
        float v = mTimePaint.measureText(replaceMhour + replaceMminutes + replaceMsecond + ":" + ":");
        canvas.drawText(replaceMhour + ":" + replaceMminutes + ":" + replaceMsecond, -v / 2, radius / 3 * 2, mTimePaint);
    }
3.4绘制刻度线(让画布旋转)

private void drgree(Canvas canvas) {

        mDegreePaint = new Paint();
        mDegreePaint.setAntiAlias(true);
        mDegreePaint.setStyle(Paint.Style.FILL);
        mDegreePaint.setColor(Color.BLACK);
        mDegreePaint.setStrokeWidth(5);
        int count = 60;
        for (int i = 0; i < count; i++) {
            if (i % 5 == 0) {
                canvas.drawLine(0, radius, 0, radius - 40, mDegreePaint);
            } else {
                canvas.drawLine(0, radius, 0, radius - 15, mDegreePaint);
            }
            canvas.rotate(360 / count, 0f, 0f);
        }
    }
3.5 画表盘上的数字

private void HourText(Canvas canvas) {
        mHourTextPaint = new Paint();
        mHourTextPaint.setStyle(Paint.Style.FILL);
        mHourTextPaint.setStrokeWidth(2);
        mHourTextPaint.setAntiAlias(true);
        mHourTextPaint.setTextSize(55);
        mHourTextPaint.setColor(Color.DKGRAY);
        mHourTextPaint.setTextAlign(Paint.Align.CENTER);
        float textheight = mHourTextPaint.getFontMetrics().bottom - mHourTextPaint.getFontMetrics().top;
        float distance = radius - 70;
        float a, b;
        for (int i = 0; i < 12; i++) {
            a = (float) (distance * Math.sin(i * 30 * Math.PI / 180));
            b = (float) (distance * Math.cos(i * 30 * Math.PI / 180));
            if (i == 0) {
                canvas.drawText("12", a, -b + textheight / 3, mHourTextPaint);
            } else {
                canvas.drawText(String.valueOf(i), a, -b + textheight / 3, mHourTextPaint);
            }
        }
    }
3.6 发送一条空消息,让时间数字,走起来

@Override
    public boolean handleMessage(Message message) {
        switch (message.what) {
            case HANDLER_MSG:
                invalidate();
                long time = System.currentTimeMillis();
                mSecond =  (time / 1000 % 60);
                mMinutes =  (time / 1000 / 60 % 60);
                mHour = (time / 1000 / 60 / 60 + 8) % 12;
                break;
        }
        return true;
    }

3.7画时针分针秒针(必须要先保存之前的画的,不然会一起动)

private void hour(Canvas canvas) {

        mHourPaint = new Paint();
        mHourPaint.setStrokeWidth(10);
        mHourPaint.setAntiAlias(true);
        mHourPaint.setStyle(Paint.Style.FILL);
        mHourPaint.setColor(Color.RED);
        canvas.rotate(mHour * 30 + mMinutes / 60 * 30, 0, 0);//其中mMinutes/60*30为时钟偏移的角度
        canvas.drawLine(0, 20, 0, -(radius -320), mHourPaint);

    }

private void minutes(Canvas canvas) {
        mMinutesPaint = new Paint();
        mMinutesPaint.setStrokeWidth(8);
        mMinutesPaint.setAntiAlias(true);
        mMinutesPaint.setColor(Color.BLUE);
        mMinutesPaint.setStyle(Paint.Style.FILL);
        canvas.rotate(mMinutes * 6, 0, 0);
        canvas.drawLine(0, 20, 0, -(radius - 200), mMinutesPaint);

    }
private void second(Canvas canvas) {
        //画秒针
        mSecondPaint = new Paint();
        mSecondPaint.setStrokeWidth(5);
        mSecondPaint.setAntiAlias(true);//设置抗锯齿
        mSecondPaint.setColor(Color.GREEN);
        mSecondPaint.setStyle(Paint.Style.FILL);
        canvas.rotate(mSecond * 6, 0, 0);
        canvas.drawLine(0, 30, 0, -(radius - 100), mSecondPaint);
    }






3.8 最后在中心画点把指针覆盖

private void Point(Canvas canvas) {
        mPointPaint = new Paint();
        mPointPaint.setStrokeWidth(5);
        mPointPaint.setStyle(Paint.Style.FILL);
        mPointPaint.setColor(Color.BLACK);
        canvas.drawCircle(0, 0, 12, mPointPaint);
    }


直接的粘的代码,看的不是很清楚,慢慢看咯害羞




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值