自定义组件-绘制时钟

1、效果图


2、Canvas对象详解

1.translate(x,y):平移,将画布的坐标原点向左右方向移动x,向上下方向移动y.canvas的默认位置是在(0,0).

    例子:画布原点假如落在(1,1),那么translate(10,10)就是在原点(1,1)基础上分别在x轴、y轴移动10,则原点变为(11,11)。
2.scale(x,y):扩大。x为水平方向的放大倍数,y为竖直方向的放大倍数。
3.rotate(angel):旋转.angle指旋转的角度,顺时针旋转。
4.transform():切变。所谓切变,其实就是把图像的顶部或底部推到一边。
5 save:用来保存Canvas的状态。save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。
6 restore:用来恢复Canvas之前保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响。save和restore要配对使用(restore可以比save少,但不能多),如果restore调用次数比save多,会引发Error。
7、drawTextOnPath 在指定的path上面绘制文字。
3、代码
package com.example.canvastest.view;

import java.util.Calendar;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.example.canvastest.DensityUtil;
import com.example.canvastest.R;

/**
 * 绘制时钟
 * 
 * @author libin
 * 
 */
public class ClockView extends View {
	// 半径
	private float radius = 200;
	private Paint mDownPaint;
	// 宽度
	private float mCirclePaintWidth = 10;
	 
	// 上面圆圈的画笔
	private Paint mOutSidePaint;
	// 画文字
	private Paint mTextPaint;

	// 文字大小
	private int textFontSize = 16;
	
	private int longLine ;
	private int shortLine;
	private int widthLine ;
	//小圆心的半径
	private int circle;
	
	private int hourDegrees;
	private int minDegrees;
	private int secDegrees;
	 

	public ClockView(Context context) {
		super(context);
		init();
	}

	public ClockView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public ClockView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init();
	}

	private void init() {
		mDownPaint = new Paint();
		mDownPaint.setColor(Color.BLACK);
		mDownPaint.setAntiAlias(true);
		mDownPaint.setStrokeWidth(mCirclePaintWidth);

		textFontSize = (int) getResources().getDimension(R.dimen.textSize);
		shortLine = (int) getResources().getDimension(R.dimen.shortLine);
		longLine = (int) getResources().getDimension(R.dimen.longLine);
		widthLine = (int) getResources().getDimension(R.dimen.widthLine);
		radius = (int) getResources().getDimension(R.dimen.circleRadius);
		circle = (int) getResources().getDimension(R.dimen.circle);
		// 上面的画笔
		mOutSidePaint = new Paint();
		mOutSidePaint.setAntiAlias(true);
		mOutSidePaint.setStrokeWidth(mCirclePaintWidth);
		mOutSidePaint.setStyle(Style.STROKE);
		mOutSidePaint.setColor(Color.BLACK);
		// 上面的画笔
		mTextPaint = new Paint();
		mTextPaint.setAntiAlias(true);
		mTextPaint.setColor(Color.BLACK);
		mTextPaint.setStrokeWidth(widthLine);
		mTextPaint.setTextAlign(Align.CENTER);
		
		mTextPaint.setTextSize(textFontSize);
		mDownPaint.setTextSize(textFontSize);
		
		mHandler.sendEmptyMessage(10);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		
		// 平移,将画布的坐标原点向左右方向移动x,向上下方向移动y.canvas的默认位置是在(0,0).
		// 例子:画布原点假如落在(1,1),那么translate(10,10)就是在原点
		// (1,1)基础上分别在x轴、y轴移动10,则原点变为(11,11)。
		canvas.translate(canvas.getWidth() / 2, canvas.getHeight() / 2); // 将位置移动画纸的坐标点:150,150
		// 画圆
		canvas.drawCircle(0, 0, radius, mOutSidePaint);
		canvas.save();

		// 绘制路径
		Path path = new Path();
		path.addArc(new RectF(-radius, -radius, radius, radius), -180, 180);
		mDownPaint.setTextAlign(Align.CENTER);

		int pathy = DensityUtil.dip2px(getContext(), -5);
		// 让文字显示到中间
		canvas.drawTextOnPath("canvas绘制钟表", path, 0, pathy, mDownPaint);
		canvas.restore();

		//绘制刻度
		canvas.save();
		canvas.rotate(210);
		float y = radius;
		int count = 60; // 总刻度数
		for (int i = 0; i < count; i++) {
			if (i % 5 == 0) {
				canvas.drawLine(0f, y-longLine+2, 0, y+mCirclePaintWidth/2 , mTextPaint);
				canvas.drawText(String.valueOf(i / 5 + 1), 0, y -mCirclePaintWidth/2-longLine, mTextPaint);

			} else {
				canvas.drawLine(0f, y  - shortLine , 0f,y-mCirclePaintWidth/2, mTextPaint);
			}
			canvas.rotate(360 / count, 0f, 0f); // 旋转画纸
		}
		canvas.restore();
	 
		
		//绘制秒针
		canvas.save();
		canvas.rotate(secDegrees);
		Paint hourPaint = new Paint(mDownPaint);
		hourPaint.setColor(Color.BLACK);
		hourPaint.setStrokeWidth(circle);
		 
		canvas.drawLine(0, -longLine, 0, radius*2/3, hourPaint);
		canvas.restore();
		
		//绘制分针
		canvas.save();
		canvas.rotate(minDegrees);
		canvas.drawLine(0, -longLine, 0, radius*1/2, hourPaint);
		canvas.restore();
	
		//绘制时针
		canvas.save();
		canvas.rotate(hourDegrees);
		canvas.drawLine(0, -longLine, 0, radius*1/3, hourPaint);
		canvas.restore();

		//绘制中心黑点
		Paint tmpPaint = new Paint(mDownPaint);
		tmpPaint.setColor(Color.BLACK);
		canvas.drawCircle(0, 0, circle*2, tmpPaint);
		 
		 
		//绘制中心红点
		tmpPaint.setColor(Color.RED);
		canvas.drawCircle(0, 0, circle*4/3, tmpPaint);
		super.onDraw(canvas);
	}
 
	/**
	 * 获取角度
	 */
	private void calculate(){
		Calendar calendar = Calendar.getInstance();
		int hour = calendar.get(Calendar.HOUR);
		if (hour>12) {
			hour = hour-12;
		}
		hourDegrees = hour*30-180;
		
		int min = calendar.get(Calendar.MINUTE);
		minDegrees = min * 6-180;
		
		int sec = calendar.get(Calendar.SECOND);
		secDegrees = sec * 6-180;
		Log.i("tag", " "+ hour+" "+min+" "+sec);
	}
	
	/**
	 * 定时器
	 */
	private Handler mHandler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case 10:
				calculate();
				invalidate();
				this.sendEmptyMessageDelayed(10, 1000);
				break;
			default:
				break;
			}
		};
	};
}
4、常量数据
    <dimen name="textSize">14sp</dimen>
    <dimen name="circleRadius">100dip</dimen>
    <dimen name="shortLine">9dip</dimen>
    <dimen name="longLine">15dip</dimen>
    <dimen name="widthLine">5dip</dimen>
    <dimen name="circle">3dip</dimen>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值