使用SurfaceViewt和Canvas实现动态时钟

概述:

很多时候我们想要自己写一些类似时钟、罗盘的控件,却又找不到合适的Demo。我想这时你可能索性就直接上图片了。在Android有Canvas和Paint这么好的画师的情况下,还是选择使用图片,的确是有一些尴尬了。下面我就利用一步一步实现自定义时钟来对这个问题做一个讲解。

错误示例:

这里我有一个“错误”的示例。这里的错误其实应该是要打上双引号的,因为它不是真的错误,只是在某些时候,它是不适当的。下面就让我们先来学习一下这个示例,了解一下这个示例中哪些是不适合使用的技术。

效果图展示:

看了上面的两张运行效果图我们可以看到很正常的两张运行图,不过这不是全部。错误信息下面再进行展示和分析。在这里我就来解释一下为什么说这个示例不是全错,只是不恰当的原因。因为如果我们的需求是不用变化的图形,例如一些多边形的展示等,不需要实时去刷新界面,OK,这个示例没有任何问题,而且使用简单。针对这一点,我想也是有必要附上代码来展示一下实现过程。

静态画图代码:public class CustomCanvasView extends View {private static final String TAG = CustomCanvasView.class.getName();private Paint paint;private int mRadius;private Canvas mCanvas;private int mHours;private int mMinutes;private int mSeconds;private Thread mThread;public CustomCanvasView(Context context, int radius) {super(context);paint = new Paint();paint.setColor(Color.RED);paint.setStrokeJoin(Paint.Join.ROUND);paint.setStrokeCap(Paint.Cap.ROUND);paint.setStrokeWidth(5);mRadius = radius;}// 在这里我们将测试canvas提供的绘制图形方法@Overrideprotected void onDraw(Canvas canvas) {mCanvas = canvas;drawCompass(mCanvas);refreshClock();}private void refreshClock() {mThread = new Thread() {@Overridepublic void run() {try {while (true) {handler.sendEmptyMessage(0x123);sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();}}};mThread.start();}Handler handler = new Handler() {public void handleMessage(Message msg) {Calendar c = Calendar.getInstance();mHours = c.getTime().getHours();mMinutes = c.getTime().getMinutes();mSeconds = c.getTime().getSeconds();invalidate();c = null;};};/*** 绘制罗盘* 2015-2-3*/private void drawCompass(Canvas canvas) {paint.setAntiAlias(true);paint.setStyle(Style.STROKE);canvas.translate(canvas.getWidth() / 2, mRadius + 300); // 平移罗盘canvas.drawCircle(0, 0, mRadius, paint); // 画圆圈// 使用path绘制路径文字canvas.save();drawLabel(canvas);canvas.restore();drawDividing(canvas);drawMinuteHand(canvas, 0);canvas = null;}/*** 绘制罗盘内侧的标签文本* 2015-2-4*/private void drawLabel(Canvas canvas) {canvas.translate(-155, -155);Path path = new Path();path.addArc(new RectF(0, 0, mRadius + 100, mRadius + 100), -180, 180);Paint citePaint = new Paint(paint);citePaint.setTextSize(30);citePaint.setStrokeWidth(1);canvas.drawTextOnPath("", path, 35, 0, citePaint);path = null;citePaint = null;canvas = null;}/*** 绘制刻度* 2015-2-4*/private void drawDividing(Canvas canvas) {Paint divdPaint = new Paint(paint); // 小刻度画笔对象divdPaint.setStrokeWidth(1);divdPaint.setTextSize(20);float y = mRadius;int count = 60; // 总刻度数canvas.rotate(35 * 360 / count, 0f, 0f);for (int i = 0; i < count; i++) {if (i % 5 == 0) {canvas.drawLine(0f, y, 0, y + 20f, paint);canvas.drawText(String.valueOf(i / 5 + 1), -4f, y + 55f, divdPaint);} else {canvas.drawLine(0f, y, 0f, y + 15f, divdPaint);}canvas.rotate(360 / count, 0f, 0f); // 旋转画纸}divdPaint = null;canvas = null;}/*** 绘制分针* 2015-2-4*/private void drawMinuteHand(Canvas canvas, int second) {Paint tmpPaint = new Paint(paint);tmpPaint.setStrokeWidth(2);tmpPaint.setTextSize(30);tmpPaint.setColor(Color.GRAY);tmpPaint.setStrokeWidth(4);canvas.drawCircle(0, 0, 10, tmpPaint);tmpPaint.setStyle(Style.FILL);tmpPaint.setColor(Color.YELLOW);canvas.drawCircle(0, 0, 5, tmpPaint);canvas.rotate(mSeconds * 6, 0f, 0f);canvas.drawLine(0, 20, 0, -135, paint);tmpPaint = null;canvas = null;}}

错误日志展示及原因分析:

说实话上面两张图看上去真的很棒,可是如果你下载了我的源码并运行之后,你可能就会发现,在你的指针走了大概20秒的时候,程序就挂了。查看日志就会发现如下错误信息:

一直有记日记的习惯,可是,旅行回来,都懒得写日记来记录,

使用SurfaceViewt和Canvas实现动态时钟

相关文章:

你感兴趣的文章:

标签云: