Android 自定义view(画表盘)

自定义View就是继承一个View的子孙类或View类,然后重写其中的一些方法来完成界面的美观效果。
效果:
这里写图片描述

布局:

    <so.wih.android.myview.MyLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

代码:

public class MyLayout extends View {

    private int mWidth;
    private int mHeight;
    private Paint mCirclePaint;
    private int circleRadius ;
    private Paint mPaintLine;
    private Paint mPaintText;
    private Calendar mCalendar;
    public static final int what_update = 100;

    public Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case what_update :
                    mCalendar=Calendar.getInstance();//这一句必须有,如果没有就不刷新时间
                    invalidate();//重绘界面 会调用onDraw方法
                    handler.sendEmptyMessageDelayed(what_update,1000);
                    break;
            }
        }
    };

    public MyLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyLayout(Context context) {
        super(context);
        init();
    }

    /**
     * 初始化控件
     */
    private void init() {
        //圆半径
        circleRadius =  300 ;
        //画圆的画笔
        mCirclePaint = new Paint();
        mCirclePaint.setColor(Color.GREEN);
        mCirclePaint.setStrokeWidth(10);//设置绘制的笔画宽度
        mCirclePaint.setStyle(Paint.Style.STROKE); //空心

        //画刻度的画笔
        mPaintLine = new Paint();
        mPaintLine.setColor(Color.RED);
        mPaintLine.setStrokeWidth(10);

        //画数字的画笔
        mPaintText = new Paint();
        mPaintText.setColor(Color.GRAY);
        mPaintText.setTextSize(35);
        mPaintText.setStrokeWidth(10);
        mPaintText.setTextAlign(Paint.Align.CENTER); //文字居中

        //发送消息
        handler.sendEmptyMessage(what_update);
        //获取时间
        mCalendar = Calendar.getInstance();
    }

    /*
     * 当一个view 从创建对象,到显示在屏幕中,的几个重要步骤:
     *
     * 1- 测量控件大小
     *      onMeasure
     * 2- 指定控件位置
     *      onLayout
     * 3- 绘制控件的内容
     *      onDraw
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 我们要做的就是设置测量大小,即,view想要的大小
        mWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(mWidth, mHeight);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 绘制大圆
        canvas.drawCircle(mWidth/2, mHeight/2, circleRadius, mCirclePaint);
        //小圆
        canvas.drawCircle(mWidth / 2, mHeight / 2, 5, mCirclePaint);

        //绘制刻度
        for (int i = 1; i <=12 ; i++) {
            //大刻度
            canvas.save(); //保存当前矩阵并将其存储到私有堆栈上
            float degrees = 360/12*i ;
            canvas.rotate(degrees,mWidth/2, mHeight/2);
            canvas.drawLine(mWidth / 2 ,(mHeight / 2-circleRadius) ,
                    mWidth / 2 ,(mHeight / 2-circleRadius+20) ,mPaintLine);
            canvas.drawText(""+i,mWidth/2,(mHeight / 2-circleRadius+50),mPaintText);
            /**
             * 这个调用是为了平衡save(),用于移除自上次保存时的矩阵/剪辑状态的所有修改。
             * 不能比svae()调用的次数多
             */
            canvas.restore();

            //小刻度
            canvas.save(); //保存当前矩阵并将其存储到私有堆栈上
            float degrees2 = 360/12*(i-1)+15 ;
            canvas.rotate(degrees2,mWidth/2, mHeight/2);
            canvas.drawLine(mWidth / 2 ,(mHeight / 2-circleRadius) ,
                    mWidth / 2 ,(mHeight / 2-circleRadius+10) ,mPaintLine);
//            canvas.drawText(""+i,mWidth/2,(mHeight / 2-circleRadius+50),mPaintText);
            /**
             * 这个调用是为了平衡save(),用于移除自上次保存时的矩阵/剪辑状态的所有修改。
             * 不能比svae()调用的次数多
             */
            canvas.restore();
        }

        //绘制时针、分针和秒针
        int hour = mCalendar.get(Calendar.HOUR);
        int minute = mCalendar.get(Calendar.MINUTE);
        int second = mCalendar.get(Calendar.SECOND);
        //小时的角度
        float hourDegree = 360 / 12f * hour ;
        canvas.save();//这个方法和restore配合用于表盘归位
        canvas.rotate(hourDegree, mWidth / 2, mHeight / 2);//以表盘中心为中心旋转现在分钟数*(360度/60分)
        canvas.drawLine(mWidth / 2 ,mHeight / 2 , mWidth / 2 ,(mHeight / 2 - circleRadius+200) ,mPaintLine);
        canvas.restore();//表盘归于原位
        //分钟的角度
        float minuteDegree = 360 / 60f * minute ;
        canvas.save();//这个方法和restore配合用于表盘归位
        canvas.rotate(minuteDegree, mWidth / 2, mHeight / 2);//以表盘中心为中心旋转现在分钟数*(360度/60分)
        canvas.drawLine(mWidth / 2 ,mHeight / 2 , mWidth / 2 ,(mHeight / 2 - circleRadius+150) ,mPaintLine);
        canvas.restore();//表盘归于原位
        //秒针的角度
        float sedondDegree = 360 /60f * second ;
        canvas.save();//这个方法和restore配合用于表盘归位
        canvas.rotate(sedondDegree, mWidth / 2, mHeight / 2);//以表盘中心为中心旋转现在分钟数*(360度/60分)
        canvas.drawLine(mWidth / 2 ,mHeight / 2 , mWidth / 2 ,(mHeight / 2 - circleRadius+100) ,mPaintLine);
        canvas.restore();//表盘归于原位


    }

}

参考自:http://blog.csdn.net/litao660044/article/details/48500417
这个大神写的自定义控件很详细。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值