【代码分析】
重写 onDraw
画外圆
/** * 画外圆和中心实心圆 * @param canvas */ private void drawCircle(Canvas canvas) { Paint paint = new Paint(); paint.setColor(mRingColor); paint.setStyle(Paint.Style.STROKE); paint.setAntiAlias(true); paint.setDither(true); paint.setStrokeWidth(getDigit(2)); canvas.drawCircle(mWidth/2, mHeight/2, mDiameter/2, paint); // 画中心的实心圆 paint.setStyle(Paint.Style.FILL); paint.setColor(mCenterPointColor); canvas.drawCircle(mWidth/2, mHeight/2, getDigit(4), paint); }
画刻度
/** * 画刻度 * @param canvas */ private void drawScale(Canvas canvas) { Paint paint = new Paint(); paint.setStrokeWidth(getDigit(1)); paint.setTextSize(getDigit(10)); paint.setAntiAlias(true); for(int i=0; i<60; i++){ if(i%5 == 0){ paint.setStrokeWidth(getDigit(2)); paint.setColor(mLongScaleColor); paint.setTextSize(getDigit(15)); String timeText = "" + i/5; if(i==0){ timeText = "12"; } canvas.drawLine(mWidth/2, mHeight/2 - mDiameter/2, mWidth/2, mHeight/2 - mDiameter/2 + 40, paint); paint.setColor(mTextColor); canvas.drawText(timeText, mWidth/2-paint.measureText(timeText)/2, mHeight/2-mDiameter/2+80, paint); } else { paint.setStrokeWidth(getDigit(1)); paint.setTextSize(getDigit(15)); paint.setColor(mShortScaleColor); canvas.drawLine(mWidth/2, mHeight/2 - mDiameter/2, mWidth/2, mHeight/2 - mDiameter/2 + 20, paint); } // 旋转画布,每次旋转6度 canvas.rotate(6,mWidth/2, mHeight/2); } }
画指针
/** * 画指针:时针,分针,秒针 * @param canvas */ private void drawIndicator(Canvas canvas) { // 保存图层 canvas.save(); canvas.translate(mWidth/2f, mHeight/2f); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setDither(true); paint.setStrokeWidth(getDigit(3)); paint.setColor(mHourColor); canvas.drawLine(0, 0, getLeftBy(H), getTopBy(H), paint); paint.setStrokeWidth(getDigit(2)); paint.setColor(mMinuteColor); canvas.drawLine(0, 0, getLeftBy(M), getTopBy(M), paint); paint.setStrokeWidth(getDigit(1)); paint.setColor(mSecondColor); canvas.drawLine(0, 0, getLeftBy(S), getTopBy(S), paint); // 合并图层 canvas.restore(); } private float getLeftBy(int indicator){ float r=0f; float digit = 0; switch(indicator){ case H: r = mHourR; // 根据分钟进行补充,每5分钟进一小格 digit = ((mHour%12/12f*60 + mMinute/60f*5)) % 60; break; case M: r = mMinuteR; digit = mMinute; break; case S: r = mSecondR; digit = mSecond+1; break; } float left = (float) Math.sin(digit/60f * Math.PI*2) * r; if(digit<=30){ return Math.abs(left); } else { return -Math.abs(left); } } private float getTopBy(int indicator){ float r=0f; float digit = 0; switch(indicator){ case H: r = mHourR; // 根据分钟进行补充,每5分钟进一小格 digit = ((mHour%12/12f*60 + mMinute/60f*5)) % 60; break; case M: r = mMinuteR; digit = mMinute; break; case S: r = mSecondR; digit = mSecond+1; break; } float left = (float) Math.cos(digit/60f * Math.PI*2) * r; if(15<=digit && digit<=45){ return Math.abs(left); } else { return -Math.abs(left); } }
重写 onMesure
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mWidth = measuredWidth(widthMeasureSpec); mHeight = measuredHeight(heightMeasureSpec); setMeasuredDimension(mWidth, mHeight); // 钟表的外圆直径(除去 padding ) mDiameter = Math.min(mWidth - getPaddingLeft() - getPaddingRight(), mHeight - getPaddingTop() - getPaddingBottom()); // 时针半径外环半径的1/3 mHourR = mDiameter/2f/3; // 分针半径为外环半径的1/2 mMinuteR = mDiameter/2f/2; // 秒针半径为外环半径的1/1.5 mSecondR = mDiameter/2f/1.5f; } private int measuredWidth(int widthMeasureSpec) { int result = 0; int specMode = MeasureSpec.getMode(widthMeasureSpec); int specSize = MeasureSpec.getSize(widthMeasureSpec); if(specMode == MeasureSpec.EXACTLY){ result = specSize; } else { result = 500; if(specMode == MeasureSpec.AT_MOST){ result = Math.min(result, specSize); } } return result; } private int measuredHeight(int heightMeasureSpec) { int result = 0; int specMode = MeasureSpec.getMode(heightMeasureSpec); int specSize = MeasureSpec.getSize(heightMeasureSpec); if(specMode == MeasureSpec.EXACTLY){ result = specSize; } else { result = 500; if(specMode == MeasureSpec.AT_MOST){ result = Math.min(result, specSize); } } return result; }
用新线程启动钟表
/** * 启动钟表 */ private void startClock(){ new Thread(new Runnable() { @Override public void run() { while (true) { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); int hour = calendar.get(Calendar.HOUR)+1; int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); setHour(hour); setMinute(minute); setSecond(second); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }
【源码下载】