Android 自定义View(四) 时钟clockView

模仿To_be_Designer的自定义时钟,主要是强化自己的技能,和写一点感悟

实现目标:

     

绘制直线:

  • drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
      
    两点确定一条直线,第一、二参数是起始点的坐标;第三、四参数是结束点的坐标;第五个参数画笔Paint对象。
  • drawLines(float[] pts, Paint paint)
      多个点确定一条直线,第一个参数是点的数组;第二个参数是画笔Paint对象。
  • drawLines(float[] pts, int offset, int count, Paint paint)

 public ClockView(Context context, AttributeSet attrs) 
   自定义视图一定要实例化带两个参数的构造方法AttributeSet参数 因为该构造器的第二个参数是与xml布局文件相联系的,  
   如果没有重写该构造器,将不能在布局中使用该控件。


首先定义了一些私有变量
    private Paint mPaintLine;  //绘制直线的画笔
    private Paint mPaintSecondLine;//定义一个绘制直线的画笔 (秒表)
    private Paint mPaintOutCircle; //绘制外圆的画笔
    private Paint mPaintInCircle; //绘制内圆的画笔
    private Paint mPaintText;//定义一个绘制文字的画笔


在你要用这些变量前设置它的属性  这里设置了颜色,笔的宽度,样式(STROKE为空心) ,抗锯齿

mPaintLine =new Paint();
mPaintLine.setColor(Color.RED);
mPaintLine.setStrokeWidth(10);
mPaintLine.setStyle(Paint.Style.STROKE);
mPaintLine.setAntiAlias(true);
其它也是如此......

mPaintSecondLine =new Paint(mPaintLine);
mPaintSecondLine.setStrokeWidth(7);

在测量方法里(onMeasure) 以前经常是  

int widthMode = getMode(widthMeasureSpec)

int widthSIze = getMode(widthMeasureSpec)
if(widthMode==MeasureSpec.EXACTLY)

{

int result  = widthSIze

}else

{

int result  =getSuggestedMinimumWidth()

}

现在可以更简便的使用getDefaultSize()方法,这是android方便开发者做的优化,具体代码入下:

//就是封装了getMode和getsize
width = getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
height = getDefaultSize(getSuggestedMinimumHeight(),widthMeasureSpec);
setMeasuredDimension(width,height);

 

onDraw 有几点需要注意 save() 和restore()成对出现

再画时钟的刻度的时候

    canvas.save();             //保存画布                                     
    canvas.rotate(360/12*i,width/2,height/2); //旋转画布 

    canvas.restore();//返回save的保存状态,这里就是变回未旋转的状态

 

//绘制分针
int minute = mCalendar.get(Calendar.MINUTE);  //Calendar是掌管时间的类 , Calendar.getInstance();创建实例
float minuteDegree = minute/60f*360;          //    (360/60f)*minute,一个刻度占多少度*minute(0-60的取值范围)
canvas.save();
canvas.rotate(minuteDegree,width/2,height/2);
canvas.drawLine(width/2,height/2-90,width/2,height/2+20,mPaintLine);
canvas.restore();

秒针同理

最难的时针,生活中时针会根据分针慢慢偏移角度,不能一下子从6点转到7点

float hourDegree = (hours*60+minute);//(12f*60)*360;  我算出来是(60*h+min)

暂时不想了

在这个时钟自定义类中我们定义了一个Handle ,Handle 有更新视图,处理消息的作用 ,invalidate()会调用onDraw(),这样就重绘了视图

//操作UI主线程
private Handler mHandle = new Handler(){

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what){
            case NEED_INVALIDATE:
                //更新时间
                mCalendar = Calendar.getInstance();
                invalidate();//请求重新draw
                //延迟1500毫秒后发送空消息
                sendEmptyMessageDelayed(NEED_INVALIDATE,1000);//这里不停的发送消息给handleMessage 就导致了不停的重绘
                break;
        }
    }
};

 

最后再有一个地方调用 ,触发这个handler

mHandler.sendEmptyMessageDelayed(MSG_PROGRESS_UPDATE, 100);

 

代码可以参考To_be_Designer   所以就不贴了 ,看To_be_Designer  和hongyang的博客能学到很多东西


阅读更多

没有更多推荐了,返回首页