自定义View(二)

一、概述

在上一篇分析了自定义View的基础知识,如果还是不清楚自定义View的请看上篇博客自定义View(一)。这篇主要是一个自定View的一个简单实例—-一个时钟效果。运行如下。

这里写图片描述

其实这个效果之前写过一篇网页版的,利用HTML5的context写的,有兴趣的可以看看。

简单分析下:
由图可以看出这个自定义View由一个圆,3个指针直线,然后就是断直线了,至于它的自动走动可以用post系列方法重复调用onDraw即可。这里的重点是canvas的rotate、translate两个方法的灵活使用。

二、代码

布局如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <com.lw.myclock.MyClock
        android:layout_width="300dp"
        android:layout_height="300dp"
        />

</RelativeLayout>

初始化方法,用来创建画笔,并且设置画笔的style和颜色

public void init(){
        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Style.STROKE);
        //去掉锯齿
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(3);
    }

获取当前时间

    //获取当前时间
    d = new Date();
    int hours = d.getHours();
    int minutes = d.getMinutes();

下面则是开始真正画了,主要是通过canvas的translate()来设置画布的中心点,然后调用rotat()e控制画布旋转来画出短线。


        //1.画圆
        canvas.translate(150, 150);
        canvas.drawCircle(0, 0, radius, mPaint);
        //2.画时钟刻度线
        for (int i = 0; i <= 11 ; i++) {
            mPaint.setStrokeWidth(3);
            canvas.drawLine(0, -150, 0, -135, mPaint) ;
            mPaint.setStrokeWidth(1);
            if( i == 0 ){
                canvas.drawText(12 + "",-5,-130,mPaint) ;
            }else{
                canvas.drawText(i + "",-5,-130,mPaint) ;
            }
            canvas.rotate(30) ;
        }
        //画分钟刻度线
        for (int i = 0; i < 60 ; i++) {
            mPaint.setStrokeWidth(1) ;
            canvas.drawLine(0, -150, 0, -145, mPaint) ;
            canvas.rotate(6);
        }

这里每次开始画之前需要调用save()方法,每次画好之后需要调用restore()方法


    //画时钟刻度指针
        canvas.save() ;
        mPaint.setStrokeWidth(4);
        canvas.rotate(hours * 30 + (minutes * 6) * 30 / 360  );
        canvas.drawLine(0, 10, 0, -90, mPaint);
        canvas.restore() ;
        //画分钟刻度指针
        canvas.save() ;
        mPaint.setStrokeWidth(2);
        //初始化分钟指针,主要让其指定到12点位置
        System.out.println("minutes:" + minutes * 6 );
        canvas.rotate(minutes * 6 ) ;
        canvas.drawLine(0, 10, 0, -100, mPaint);
        canvas.restore() ;
        //画秒钟刻度线
        canvas.save() ;
        mPaint.setStrokeWidth(1);
        canvas.rotate(seconds * 6 );
        System.out.println("seconds:" + seconds);
        canvas.drawLine(0, 10, 0, -120, mPaint) ;
        canvas.restore() ;
        //画中心圆点
        canvas.save() ;
        mPaint.setStrokeWidth(3);
        canvas.drawCircle(0, 0, 2, mPaint);
        canvas.restore() ;

这里比较复杂的是时钟角度的变化

canvas.rotate(hours * 30 + (minutes * 6) * 30 / 360  ) ;

假如此时时间是11点30分,11点则是hours * 30,30分钟旋转的角度则是 (minutes * 6) * 30 / 360 。

然后就开始调用post方法每一个1s调用。
全部代码如下:

package com.lw.myclock;

import java.util.Date;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;
/**
 * 自定义时钟
 * @author lw
 *
 */
public class MyClock extends View {

    private Paint mPaint = new Paint();
    private Date d;

    public MyClock(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    public MyClock(Context context) {
        this(context,null);
    }
    public void init(){
        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Style.STROKE);
        //去掉锯齿
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(3);
    }

    @Override
    protected void onDraw(final Canvas canvas) {
        super.onDraw(canvas);

        int width = getWidth();
        int height = getHeight();
        int paddingBottom = getPaddingBottom();
        int paddingTop = getPaddingTop();
        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        width = width - paddingLeft - paddingRight ;
        height = height - paddingBottom - paddingTop ;
        //300 300 
        //获取当前时间
        d = new Date();
        int hours = d.getHours();
        int minutes = d.getMinutes();
        int seconds = d.getSeconds();
        int radius = Math.min(width, height) / 2 ;
        //1.画圆
        canvas.translate(150, 150);
        canvas.drawCircle(0, 0, radius, mPaint);
        //2.画时钟刻度线
        for (int i = 0; i <= 11 ; i++) {
            mPaint.setStrokeWidth(3);
            canvas.drawLine(0, -150, 0, -135, mPaint) ;
            mPaint.setStrokeWidth(1);
            if( i == 0 ){
                canvas.drawText(12 + "",-5,-130,mPaint) ;
            }else{
                canvas.drawText(i + "",-5,-130,mPaint) ;
            }
            canvas.rotate(30) ;
        }
        //画分钟刻度线
        for (int i = 0; i < 60 ; i++) {
            mPaint.setStrokeWidth(1) ;
            canvas.drawLine(0, -150, 0, -145, mPaint) ;
            canvas.rotate(6);
        }
        //画时钟刻度指针
        canvas.save() ;
        mPaint.setStrokeWidth(4);
        canvas.rotate(hours * 30 + (minutes * 6) * 30 / 360  ) ;
        canvas.drawLine(0, 10, 0, -90, mPaint);
        canvas.restore() ;
        //画分钟刻度指针
        canvas.save() ;
        mPaint.setStrokeWidth(2);
        //初始化分钟指针,主要让其指定到12点位置
        System.out.println("minutes:" + minutes * 6 );
        canvas.rotate(minutes * 6 ) ;
        canvas.drawLine(0, 10, 0, -100, mPaint);
        canvas.restore() ;
        //画秒钟刻度线
        canvas.save() ;
        mPaint.setStrokeWidth(1);
        canvas.rotate(seconds * 6 );
        System.out.println("seconds:" + seconds);
        canvas.drawLine(0, 10, 0, -120, mPaint) ;
        canvas.restore() ;
        //画中心圆点
        canvas.save() ;
        mPaint.setStrokeWidth(3);
        canvas.drawCircle(0, 0, 2, mPaint);
        canvas.restore() ;
        //递归调用
        postInvalidateDelayed(1000) ;
    }
}

OK,这个简单实例到这就结束了。

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值