自定义 View 实现钟表效果

来源:互联网 发布:ubuntu镜像下载地址 编辑:程序博客网 时间:2024/05/23 11:53

一个很简单的自定义实例,直接上代码,注释已经写得很清楚了

attrs:

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="MyClockView">        <attr name="wb_radius" format="dimension"/>        <!--背景颜色-->        <attr name="wb_background_color" format="color"/>        <!--0369点刻度颜色-->        <attr name="wb_scale_large_long_color" format="color"/>        <!--时刻刻度颜色-->        <attr name="wb_scale_long_color" format="color"/>        <!--非时刻刻度颜色-->        <attr name="wb_scale_short_color" format="color"/>        <!--时针颜色-->        <attr name="wb_hour_pointer_color" format="color"/>        <!--分针颜色-->        <attr name="wb_minute_pointer_color" format="color"/>        <!--秒针颜色-->        <attr name="wb_second_pointer_color" format="color"/>        <!--主题风格-->        <attr name="wb_type" format="integer"/>    </declare-styleable></resources>


MyClockView:

public class MyClockView extends View {    private float mRadius; //外圆半径    private int mBackground; //背景颜色    private int mColorLong; //长线的颜色    private int mColorShort; //短线的颜色    private int mColorLargeLong; //0369点刻度颜色    private int mHourPointColor; //时针的颜色    private int mMinutePointColor; //分针的颜色    private int mSecondPointColor; //秒针的颜色    private int mType; //风格类型    private Paint mPaint; //画笔    private Calendar calendar;    private float angleHour; //时针转过的角度    private int angleMinute, angleSecond; //分针和秒针转过的角度    private Bitmap background; //背景图片    private Rect backgroundRect; // 用于缩放背景图片的矩形    private float oneUnit; // 一个单位的长度,由半径得到    private final static int NORMAL = 1; //普通风格    private final static int FRESH = 2; //清新风格    public MyClockView(Context context) {        this(context, null);    }    public MyClockView(Context context, AttributeSet attrs) {        super(context, attrs);        initAttrs(context, attrs);        initPaint();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//        取计算的长度和宽度的最小值,保证view所占空间为正方形        int specSize = Math.min(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));        setMeasuredDimension(specSize, specSize);        if (mRadius == - 1) //如果未设置半径,把半径设为view的长度的一半            mRadius = specSize / 2;        int intRadius = (int) mRadius;        backgroundRect = new Rect(-intRadius, -intRadius, intRadius, intRadius);        oneUnit = (float) (mRadius / 118.5);    }    @Override    protected void onDraw(Canvas canvas) {        calendar = Calendar.getInstance();        int hour = calendar.get(Calendar.HOUR); //时        int minute = calendar.get(Calendar.MINUTE); //分        int second = calendar.get(Calendar.SECOND); //秒        int milliSecond = calendar.get(Calendar.MILLISECOND);        angleHour = ((hour + (minute + second * 1.0f / 60) * 1.0f / 60)) * 360 / 12; //时针转过的角度        angleMinute = minute * 360 / 60; //分针转过的角度        angleSecond = second * 360 / 60; //秒针转过的角度        canvas.translate(getMeasuredWidth() / 2, getMeasuredHeight() / 2);//        根据设置的风格进行绘制        if (mType == NORMAL) {            drawNormal(canvas);        } else if (mType == FRESH) {            drawFresh(canvas);        }//        每秒绘制一次        postInvalidateDelayed(1000 - milliSecond);    }    //    初始化attr    private void initAttrs(Context context, AttributeSet attrs) {        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyClockView);        mBackground = ta.getColor(R.styleable.MyClockView_wb_background_color, Color.WHITE);        mColorLong = ta.getColor(R.styleable.MyClockView_wb_scale_long_color, Color.BLACK);        mColorLargeLong = ta.getColor(R.styleable.MyClockView_wb_scale_large_long_color, mColorLong);        mColorShort = ta.getColor(R.styleable.MyClockView_wb_scale_short_color, Color.BLACK);        mHourPointColor = ta.getColor(R.styleable.MyClockView_wb_hour_pointer_color, Color.BLACK);        mMinutePointColor = ta.getColor(R.styleable.MyClockView_wb_minute_pointer_color, Color.BLACK);        mSecondPointColor = ta.getColor(R.styleable.MyClockView_wb_second_pointer_color, Color.BLACK);        mType = ta.getInt(R.styleable.MyClockView_wb_type, NORMAL);        mRadius = ta.getDimension(R.styleable.MyClockView_wb_radius, - 1); //如果未设置半径,默认值为-1        if (mType == NORMAL) {            background = BitmapFactory.decodeResource(getResources(), R.drawable.clock);        }        ta.recycle();    }    //    初始化画笔    private void initPaint() {        mPaint = new Paint();        mPaint.setAntiAlias(true);    }    //    计算宽度    private int measureWidth(int measureSpec) {        int result = 0;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if (specMode == MeasureSpec.EXACTLY) {            result = specSize;        } else {            //若长度为wrap_content,如果未设置半径,把长度设为200,否则长度为半径的两倍            if (specMode == MeasureSpec.AT_MOST) {                if (mRadius == - 1) {                    result = 200;                } else {                    result = (int) (mRadius * 2);                }            }        }        return result;    }    //    计算高度    private int measureHeight(int measureSpec) {        int result = 0;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if (specMode == MeasureSpec.EXACTLY) {            return specSize;        } else {            if (specMode == MeasureSpec.AT_MOST) {                if (mRadius == - 1) {                    result = 200;                } else {                    result = (int) (mRadius * 2);                }            }        }        return result;    }//    绘制普通风格    private void drawNormal(Canvas canvas) {        //绘制背景        canvas.drawBitmap(background, null, backgroundRect, null);//        绘制刻度        canvas.save();        mPaint.setColor(mColorLargeLong);        mPaint.setStrokeWidth(oneUnit);        mPaint.setStyle(Paint.Style.FILL);        for (int i = 0; i <= 12; i++) {            canvas.drawLine(0, -oneUnit * 78, 0, -oneUnit * 73, mPaint);            canvas.rotate(30);        }        canvas.restore();//        绘制时针        canvas.save();        float hourWidth = (float) (oneUnit * 1.6);        mPaint.setColor(mHourPointColor);        mPaint.setStrokeWidth(0);        Path path = new Path();        path.moveTo(-hourWidth, oneUnit * 15);        path.lineTo(hourWidth, oneUnit * 15);        path.lineTo(oneUnit, -oneUnit * 50);        path.lineTo(-oneUnit, -oneUnit * 50);        path.close();        canvas.rotate(angleHour);        canvas.drawPath(path, mPaint);        canvas.restore();//        绘制分针        canvas.save();        mPaint.setColor(mMinutePointColor);        path.moveTo((float) (-oneUnit * 1.5), oneUnit * 15);        path.lineTo((float) (oneUnit * 1.5), oneUnit * 15);        path.lineTo((float) (oneUnit * 0.8), -oneUnit * 63);        path.lineTo((float) (-oneUnit * 0.8), -oneUnit * 63);        path.close();        canvas.rotate(angleMinute);        canvas.drawPath(path, mPaint);        canvas.restore();//        绘制秒针        canvas.save();        mPaint.setColor(mSecondPointColor);        mPaint.setStrokeWidth((float) (oneUnit * 1.6));        canvas.rotate(angleSecond);        canvas.drawLine(0, -oneUnit * 72, 0, oneUnit * 15, mPaint);        canvas.restore();//        绘制中心点        mPaint.setStrokeWidth(0);        canvas.drawCircle(0, 0, oneUnit * 4, mPaint);    }//    绘制清新风格    private void drawFresh(Canvas canvas) {        canvas.save();        mPaint.setColor(mBackground);        mPaint.setStyle(Paint.Style.FILL);        canvas.drawCircle(0, 0, mRadius, mPaint);        canvas.restore();        canvas.save();        mPaint.setColor(mColorLargeLong);        mPaint.setStrokeWidth(0);        RectF largeLongRectF = new RectF(-oneUnit, -mRadius, oneUnit, (-mRadius + oneUnit * 20));        for (int i = 0; i <= 4; i++) {            canvas.drawRoundRect(largeLongRectF, oneUnit, oneUnit, mPaint);            canvas.rotate(90);        }        mPaint.setColor(mColorLong);        RectF longRectF = new RectF(-oneUnit, -mRadius, oneUnit, (-mRadius + oneUnit * 31));        for (int i = 0; i <= 12; i++) {            if (i % 3 != 0) {                canvas.drawRoundRect(longRectF, oneUnit, oneUnit, mPaint);            }            canvas.rotate(30);        }        mPaint.setColor(mColorShort);        RectF shortRectF = new RectF(-oneUnit, -mRadius, oneUnit, -mRadius + oneUnit * 6);        for (int i = 0; i <= 60; i++) {            if (i % 5 != 0) {                canvas.drawRoundRect(shortRectF, oneUnit, oneUnit, mPaint);            }            canvas.rotate(6);        }        canvas.restore();        canvas.save();        float hourWidth = (float) (oneUnit * 3.5);        RectF hourRectF = new RectF(-hourWidth, -oneUnit * 61, hourWidth, 0);        mPaint.setColor(mHourPointColor);        canvas.rotate(angleHour);        canvas.drawRoundRect(hourRectF, hourWidth, hourWidth, mPaint);        canvas.restore();        canvas.save();        RectF minRectF = new RectF(-hourWidth, -oneUnit * 78, hourWidth, 0);        mPaint.setColor(mMinutePointColor);        canvas.rotate(angleMinute);        canvas.drawRoundRect(minRectF, hourWidth, hourWidth, mPaint);        canvas.restore();        canvas.save();        float secondWidth = (float) (oneUnit * 1.5);        RectF secondRectF = new RectF(-secondWidth, -mRadius, secondWidth, oneUnit * 20);        mPaint.setColor(mSecondPointColor);        canvas.rotate(angleSecond);        canvas.drawRoundRect(secondRectF, secondWidth, secondWidth, mPaint);        canvas.restore();        mPaint.setColor(mHourPointColor);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setStrokeWidth((float) (oneUnit * 2.5));        canvas.drawCircle(0, 0, (float) (oneUnit * 5.25), mPaint);        mPaint.setColor(mSecondPointColor);        mPaint.setStyle(Paint.Style.FILL);        mPaint.setStrokeWidth(0);        canvas.drawCircle(0, 0, oneUnit * 4, mPaint);    }}


添加到 Activity:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:custom="http://schemas.android.com/apk/res-auto"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.ivy.module.app.MainActivity">    <com.ivy.module.app.MyClockView        android:layout_width="220dp"        android:layout_height="220dp"        android:layout_gravity="center_horizontal"        custom:wb_hour_pointer_color="@android:color/black"        custom:wb_minute_pointer_color="#A996FF"        custom:wb_second_pointer_color="#FF0000"        custom:wb_scale_large_long_color="#cec8d8"        custom:wb_scale_long_color="#cec8d8"        custom:wb_type="1"/>    <com.ivy.module.app.MyClockView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center_horizontal"        custom:wb_radius="120dp"        custom:wb_hour_pointer_color="#413c5a"        custom:wb_minute_pointer_color="#BCACEE"        custom:wb_second_pointer_color="#FF3B7A"        custom:wb_scale_large_long_color="#9888E0"        custom:wb_scale_long_color="#D4CBF2"        custom:wb_scale_short_color="#CBC5E9"        custom:wb_type="2"/></LinearLayout>


效果图:



0 0
原创粉丝点击