自定义View实现米老鼠时钟
2016-01-21 12:49
495 查看
先看效果图,米老鼠的两个手分别指向时钟和分钟,然后米老鼠的脚在一秒执行一次动画操作。
![](https://img-blog.csdn.net/20160121124912583?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
分析完之后就先实现gif的播放,
![](https://img-blog.csdn.net/20160121125200775?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
如果实现gif的播放,就想着使用SurfaceView实现每格一秒循环一次贞动画。于是就需要8张贞图片,然后在surfaceView的125ms时间内播放一个贞,最后1000ms也就是1s播放了一次米老鼠跺脚的行为。代码如下:
/******/
分析完之后就先实现gif的播放,
如果实现gif的播放,就想着使用SurfaceView实现每格一秒循环一次贞动画。于是就需要8张贞图片,然后在surfaceView的125ms时间内播放一个贞,最后1000ms也就是1s播放了一次米老鼠跺脚的行为。代码如下:
private int count=0;
/******/
while (mIsDrawing) { long start = System.currentTimeMillis(); draw(count); //0-7时候count++;到8时候count=0; if (count<7){ count++; }else { count=0; } long end = System.currentTimeMillis(); try { if (end - start < 125) { Thread.sleep(125 - (end - start)); } } catch (InterruptedException e) { e.printStackTrace(); }
分析完了播放1s跺脚动画之后就需要实现两个手的绘制。
首先需要的就是测量中心点和半径长度:
int widthSpecMode=MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize=MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode=MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize=MeasureSpec.getSize(heightMeasureSpec); if (widthSpecMode==MeasureSpec.AT_MOST||heightSpecMode==MeasureSpec.AT_MOST){ width = Math.min(getMeasuredHeight() , getMeasuredWidth() ); setMeasuredDimension(width, width); }else { width=Math.min(widthSpecSize,heightSpecSize); setMeasuredDimension(width,width); } //中心点 mCenter=width/2; //半径 mRadius=mCenter-getPaddingLeft()-getPaddingRight(); 中心点是width/2和getMeasuredHeight() /2的中心坐标
半径就是mRadius=mCenter-getPaddingLeft()-getPaddingRight();
测量完之后确定时钟和分钟的图片长度
//时分秒的长度 hDimension = mRadius * 2 / 3 ; mDimension = mRadius *4/5;
最后要绘制这两个过程了:
Calendar c = Calendar.getInstance(); int hour = c.get(Calendar.HOUR_OF_DAY); Log.e("hour",hour+""); int minute = c.get(Calendar.MINUTE); Log.e("minute",minute+""); //3个角度 int minutefloat = minute * 360/ 60 ; Log.e("minutefloat",minutefloat+""); int hourfloat = ((hour % 12)) * 360/ 12 +minute*360/60/12; Log.e("hourfloat",hourfloat+"");上述代码是计算时钟和分钟对应的角度,当我们计算完了角度之后就可以使用
mCanvas.save();
mCanvas.rotate
mCanvas.restore();实现画布旋转和绘制图层叠加。
下面分别是绘制分钟,背景和时钟。
private void drawminite(int angle) { mCanvas.save(); //以中心坐标旋转画布画分钟手势图 mCanvas.rotate(angle, mCenter, getMeasuredHeight() / 2); int imgsWidth = (int) (mRadius/3); Rect rectm = new Rect(mCenter - imgsWidth / 2, getMeasuredHeight()/2 - mDimension, mCenter + imgsWidth / 2, getMeasuredHeight() / 2 ); mCanvas.drawBitmap(mImgsBitmap[1], null, rectm, null); mCanvas.restore(); } private void drawBg(int count) { mCanvas.drawColor(Color.TRANSPARENT); mCanvas.drawBitmap(mBgBitmap[count],null,new Rect(0,getMeasuredHeight()/2-getMeasuredWidth()/2,getMeasuredWidth(),getMeasuredHeight()/2+getMeasuredWidth()/2),null); } private void drawhour(int angle) { mCanvas.rotate(angle,mCenter,getMeasuredHeight()/2); //秒钟宽度 int imgsWidth = (int) (mRadius/3); Rect recth = new Rect(mCenter - imgsWidth / 2, getMeasuredHeight()/2 - hDimension, mCenter + imgsWidth / 2, getMeasuredHeight()/2); mCanvas.drawBitmap(mImgsBitmap[0], null, recth, null); }
所有的绘制过程就这样绘制完毕,当然所有的绘制都应该在SurfaceView的一个绘制框架内完成。下面贴出完整的代码:
package com.example.admin.customclock.customView;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.example.admin.customclock.R;
import java.util.Calendar;
/**
* Created by admin on 2016/1/20.
*/
public class ClockView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder mHolder;
private Canvas mCanvas;
private boolean mIsDrawing;
private Thread t;
private int mRadius;
//时分秒图片资源
private int[] mclockimgs = new int[]{
R.drawable.hhand,
R.drawable.mhand,
R.drawable.shand};
//时分秒的长度
private int hDimension;
private int mDimension;
private int sDimension;
private int width;
//图片资源转Bitmap
private Bitmap[] mImgsBitmap=new Bitmap[3];
//中心点
private int mCenter;
private int mPadding;
private Bitmap[] mBgBitmap=new Bitmap[8];
private int[] mBgImages = new int[]{
R.drawable.clock_1,
R.drawable.clock_2,
R.drawable.clock_3,
R.drawable.clock_4,
R.drawable.clock_5,
R.drawable.clock_6,
R.drawable.clock_7,
R.drawable.clock_8
};
private int count=0;
public ClockView(Context context) {
this(context, null);
}
public ClockView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ClockView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode=MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize=MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode=MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize=MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode==MeasureSpec.AT_MOST||heightSpecMode==MeasureSpec.AT_MOST){
width = Math.min(getMeasuredHeight() , getMeasuredWidth() );
setMeasuredDimension(width, width);
}else {
width=Math.min(widthSpecSize,heightSpecSize);
setMeasuredDimension(width,width);
}
//中心点
mCenter=width/2;
//半径
mRadius=mCenter-getPaddingLeft()-getPaddingRight();
//时分秒的长度
hDimension = mRadius * 2 / 3 ;
mDimension =
e699
mRadius *4/5;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
for (int i=0;i<8;i++){
mBgBitmap[i] = BitmapFactory.decodeResource(getResources(), mBgImages[i]);
}
mImgsBitmap = new Bitmap[3];
for (int i = 0; i < 3; i++) {
mImgsBitmap[i] = BitmapFactory.decodeResource(getResources(), mclockimgs[i]);
}
mIsDrawing = true;
t = new Thread(this);
t.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsDrawing = false;
}
@Override
public void run() {
while (mIsDrawing) { long start = System.currentTimeMillis(); draw(count); //0-7时候count++;到8时候count=0; if (count<7){ count++; }else { count=0; } long end = System.currentTimeMillis(); try { if (end - start < 125) { Thread.sleep(125 - (end - start)); } } catch (InterruptedException e) { e.printStackTrace(); }
}
}
private void draw(int count) {
try {
mCanvas = mHolder.lockCanvas();
if (mCanvas != null) {
//...
Calendar c = Calendar.getInstance(); int hour = c.get(Calendar.HOUR_OF_DAY); Log.e("hour",hour+""); int minute = c.get(Calendar.MINUTE); Log.e("minute",minute+""); //3个角度 int minutefloat = minute * 360/ 60 ; Log.e("minutefloat",minutefloat+""); int hourfloat = ((hour % 12)) * 360/ 12 +minute*360/60/12; Log.e("hourfloat",hourfloat+"");
drawBg(count);
drawminite(minutefloat);
mCanvas.save();
drawhour(hourfloat);
mCanvas.restore();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (mCanvas != null)
mHolder.unlockCanvasAndPost(mCanvas);
}
}
private void drawminite(int angle) { mCanvas.save(); //以中心坐标旋转画布画分钟手势图 mCanvas.rotate(angle, mCenter, getMeasuredHeight() / 2); int imgsWidth = (int) (mRadius/3); Rect rectm = new Rect(mCenter - imgsWidth / 2, getMeasuredHeight()/2 - mDimension, mCenter + imgsWidth / 2, getMeasuredHeight() / 2 ); mCanvas.drawBitmap(mImgsBitmap[1], null, rectm, null); mCanvas.restore(); } private void drawBg(int count) { mCanvas.drawColor(Color.TRANSPARENT); mCanvas.drawBitmap(mBgBitmap[count],null,new Rect(0,getMeasuredHeight()/2-getMeasuredWidth()/2,getMeasuredWidth(),getMeasuredHeight()/2+getMeasuredWidth()/2),null); } private void drawhour(int angle) { mCanvas.rotate(angle,mCenter,getMeasuredHeight()/2); //秒钟宽度 int imgsWidth = (int) (mRadius/3); Rect recth = new Rect(mCenter - imgsWidth / 2, getMeasuredHeight()/2 - hDimension, mCenter + imgsWidth / 2, getMeasuredHeight()/2); mCanvas.drawBitmap(mImgsBitmap[0], null, recth, null); }
}
源码下载地址:http://download.csdn.net/download/u012515603/9412799
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories