1、效果图
2、Canvas对象详解
1.translate(x,y):平移,将画布的坐标原点向左右方向移动x,向上下方向移动y.canvas的默认位置是在(0,0).
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上面绘制文字。
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>