自定义组件-绘制时钟
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():切变。所谓切变,其实就是把图像的顶部或底部推到一边。
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>