自定义View 手表表盘

来源:互联网 发布:飞车 战车 数据 编辑:程序博客网 时间:2024/04/27 12:40

最近想好好熟悉下自定义View的相关知识。Android应用开发少了自定义View真是一个缺口,关键使用而且有趣。

下面是参考别人的代码自己改装写下来的一个表盘,不说多了,从模仿开始。具体代码如下:


package com.example.xxiang1x.teststudio;import android.annotation.TargetApi;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.os.Build;import android.os.Handler;import android.os.Looper;import android.util.AttributeSet;import android.view.View;import java.util.Calendar;import java.util.GregorianCalendar;/** * 手表表盘 */public class WatchView extends View {    //create some variables    private Paint minPaint;    private Paint secondPaint;    private Paint hourPaint;    private Paint circlePaint;    private Paint textPaint;    private Paint linePaint;    //width and height    private int mWidth;    private int mHeight;    private static final double ROUND = 2d * Math.PI;    private static final double QUARTER = 1d / 4d;    private Handler mHandler = new Handler(Looper.getMainLooper());    private Calendar calendar = new GregorianCalendar();    public WatchView(Context context) {        super(context);    }    public WatchView(Context context, AttributeSet attrs) {        super(context, attrs);        initPaint();    }    /**     * 创建所有的paint     */    private void initPaint() {        minPaint = getAvailablePaint(Color.BLUE, 0, 15, Paint.Style.FILL_AND_STROKE);        secondPaint = getAvailablePaint(Color.RED, 0, 15, Paint.Style.FILL_AND_STROKE);        hourPaint = getAvailablePaint(Color.GRAY, 0, 15, Paint.Style.FILL_AND_STROKE);        circlePaint = getAvailablePaint(Color.GRAY, 5, 10, Paint.Style.STROKE);        textPaint = getAvailablePaint(Color.GRAY, 45, 3, Paint.Style.FILL);        linePaint = getAvailablePaint(Color.GRAY, 45, 3, Paint.Style.FILL);    }    /**     * get a paint by ur request.     *     * @param color     * @param textSize     * @param strockWidth     * @param style     * @return     */    private Paint getAvailablePaint(int color, int textSize, int strockWidth, Paint.Style style) {        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FAKE_BOLD_TEXT_FLAG);        paint.setAntiAlias(true);        paint.setTextSize(textSize);        paint.setAlpha(1);        paint.setColor(color);        paint.setStyle(style);        paint.setStrokeWidth(strockWidth);        paint.setStrokeCap(Paint.Cap.ROUND);        paint.setTextAlign(Paint.Align.CENTER);        paint.setStrokeCap(Paint.Cap.ROUND);        paint.setDither(true);//设置图像抖动处理        paint.setStrokeJoin(Paint.Join.ROUND);//画笔线等连接处的轮廓样式        paint.setSubpixelText(true);        return paint;    }    @TargetApi(Build.VERSION_CODES.LOLLIPOP)    public WatchView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int x = mWidth / 2;        int y = mHeight / 2;        //r        int radius = Math.min(x, y) - 10;        // 为了让秒针连续转动,所以秒针的角度肯定不是从「秒」这个整数里来        // 刚好秒针走一圈是 1 分钟,那么,就用分乘以「一圈(2π)」就是秒针要走的弧度数了        float millis = calendar.get(Calendar.MILLISECOND) / 1000f;        float second = (calendar.get(Calendar.SECOND) + millis) / 60f;        float minute = (calendar.get(Calendar.MINUTE) + second) / 60f;        float hour = (calendar.get(Calendar.HOUR) + minute) / 12f;        drawHand(canvas, hourPaint, x, y, radius * 0.5f, hour);        drawHand(canvas, minPaint, x, y, radius * 0.6f, minute);        drawHand(canvas, secondPaint, x, y, radius * 0.7f, second);        //draw the hour line .        drawHourNumbers(canvas, textPaint, mWidth, mHeight);        //draw the minutes line .        drawMinuteLine(canvas, linePaint, mWidth, mHeight);        //draw outer circle        circlePaint.setColor(Color.GRAY);        canvas.drawCircle(x, y, radius, circlePaint);        //draw center point        circlePaint.setColor(Color.YELLOW);        canvas.drawCircle(x, y, 3, circlePaint);    }    /**     * 画小时的线     *     * @param canvas     * @param paint     * @param width     * @param height     */    private void drawHourNumbers(Canvas canvas, Paint paint, int width, int height) {        int hours = 12;        int i = 0;        for (i = 1; i < 13; i++) {            canvas.save(); //save current state of canvas.            canvas.rotate(360 / 12 * i, width / 2, height / 2);            //绘制表盘            canvas.drawLine(width / 2, height / 2 - (width / 2 - 20), width / 2, height / 2 - width / 2 + 40, paint);            //绘制文字            canvas.drawText("" + i, width / 2, height / 2 - width / 2 + 80, paint);            //恢复开始位置            canvas.restore();        }    }    /**     * 画分钟的线     *     * @param canvas     * @param paint     * @param width     * @param height     */    private void drawMinuteLine(Canvas canvas, Paint paint, int width, int height) {        for (int i = 1; i < 61; i++) {            canvas.save(); //save current state of canvas.            canvas.rotate(360 / 12 / 5 * i, width / 2, height / 2);            //绘制表盘            canvas.drawLine(width / 2, height / 2 - (width / 2 - 20), width / 2, height / 2 - width / 2 + 30, paint);            //恢复开始位置            canvas.restore();        }    }    /**     * @param canvas     * @param paint     * @param x     * @param y     * @param length     * @param round     */    private void drawHand(Canvas canvas, Paint paint, float x, float y, float length, float round) {        // 三角函数的坐标轴是以 3 点方向为 0 的,所以记得要减去四分之一个圆周哦        double radians = (round - QUARTER) * ROUND;        canvas.drawLine(                x,                y,                x + (float) Math.cos(radians) * length,                y + (float) Math.sin(radians) * length,                paint);    }    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();        mHandler.post(r);    }    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        mHandler.removeCallbacksAndMessages(null);//remove all of the messages.    }    Runnable r = new Runnable() {        @Override        public void run() {            calendar.setTimeInMillis(System.currentTimeMillis());            invalidate();            mHandler.postDelayed(this, 1000 / 60);        }    };    /**     * 获取宽和高     *     * @param widthMeasureSpec     * @param heightMeasureSpec     */    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        mWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);        mHeight = getDefaultSize(getSuggestedMinimumWidth(), heightMeasureSpec);    }}

效果图:没有在真机上面测试,擦,模拟器也太模糊了,retina显示屏下面是这个鬼。




0 0