自定义view(二)

  这里是自定义view(二),上一篇关于自定义view的一些基本知识,比如说自定义view的步骤、会涉及到哪些函数以及如何实现自定义属性,同时实现了一个很基础的自定义控件,一个自定义的计时器,需要看的人可以点击这个链接:http://www.cnblogs.com/YaoJianXun/p/5806926.html。

  这次讲的是如何通过坐标系的变化实现一些更复杂的自定义view绘制,上一次博客我们实现了一个类似于计时器的环形控件,这次我们在那个基础上再做一次改动,通过坐标系的变动实现下面的效果:

  这里想讲一下关于android坐标系的一些东西:

1、android 坐标系

  在android中有两种常用坐标系:

1.1 android坐标系

  android坐标系就是以屏幕左上方为原点,向右为x轴正方向,向下为y轴正方的坐标系,可以使用getLocationOnScreen(intlocation[])这个函数获取Android坐标系中点的位置,可就是视图左上角在android坐标系中的位置。

1.2 视图坐标系

  这个坐标系描述的是子视图在父视图中的位置,就是子视图左上角在父视图总的位置,坐标系的原点在父视图的左上角,向右为x轴正方向,向下为y轴正方向。

1.3 坐标系常用函数

  • view的方法:

  getTop():获取到的是view自身顶边到期父布局顶边的距离。

getLeft():获取到的是view自身的左边到其父布局左边的距离。

getBottom(),getRight()也同上,获取的分别是view自身下边右边到其父布局下边右边的距离。

  • MotionEvent的方法:

  getX():获取点击事件距离控件左边的距离,视图坐标。

getY():获取点击事件距离控件上边的距离,视图坐标。

getRawX(),getRawY(),同上,只是他们获取的android坐标系中的距离,绝对坐标。

1.4 通过坐标系移动实现view绘制

  这里介绍两个函数:

  • translate():平移android坐标系
  • rotate():旋转android坐标系

  分析上面图中的效果如何实现:

  • 外围的圆形

  这个就不做讲述了,很容易实现的效果。

  • 表盘上的刻度

  这个就要分析一下了,首先画出12点的刻度很容,由于它是一条竖直的直线,只需要指定起止点就可以直接绘制出来了。那么其他的刻度呢,起止点就没有那么容易计算得到了,那么怎么办呢,这个时候其实只要将android坐标系以原点为中心旋转一定的角度,在绘制和12点方向一样的线,就可以了,只不过刻度不同,可能线的长度不同,这个需要设置条件语句进行具体判断,但是绘制的方向很容易就得出来了。下面是代码:

      for (int i = 0; i < 60; i++) {
            //通过旋转坐标系绘制刻度
            String degree = String.valueOf(i / 5);
            if (i % 15 == 0) {
                mPaint2.setStrokeWidth(5);
                mPaint2.setTextSize(30);
                canvas.drawLine(mCircleXY, 20, mCircleXY, 80, mPaint2);
                if (i == 0) {
                    canvas.drawText("12", mCircleXY - mPaint2.measureText(degree) / 2, 120, mPaint2);
                } else {
                    canvas.drawText(degree, mCircleXY - mPaint2.measureText(degree) / 2, 120, mPaint2);
                }
            } else if (i % 5 == 0) {
                mPaint2.setStrokeWidth(5);
                mPaint2.setTextSize(30);
                canvas.drawLine(mCircleXY, 20, mCircleXY,60, mPaint2);
                canvas.drawText(degree, mCircleXY - mPaint2.measureText(degree) / 2, 100, mPaint2);
            } else {
                mPaint2.setStrokeWidth(5);
                mPaint2.setTextSize(30);
                canvas.drawLine(mCircleXY, 20, mCircleXY, 40, mPaint2);
            }
            canvas.rotate(6, mCircleXY, mCircleXY);
        }

  通过上面的代码也能看出,每次选择6度一共旋转60次,每次绘制线的时候判断一下,如果现在整点数,绘制的线长度长一点,如果是12点、3点、6点、9点绘制的线的长度要更长一点。

  • 绘制时针分针

  这个就更简单了,通过translate()函数移动android坐标系原点到表盘中间,在从中间画出两条长短不一的线就可以了。同时没过一秒,选择一定角度就可以了。下面是代码:

     //平移坐标系,绘制时针
        canvas.translate(mCircleXY, mCircleXY);
        canvas.drawLine(0, 0, 100, 100, mPaint3);

        //旋转坐标系,绘制分针
        canvas.rotate(6 * time, 0, 0);
        canvas.drawLine(0, 0, 100, 200, mPaint4);

        time++;
        postInvalidateDelayed(1000);

  下面是完整的全部代码:

public class CustomView extends View {
    private float mCircleXY, mLength, mRadius;
    private Paint mPaint1 = new Paint();   //表圆弧
    private Paint mPaint2 = new Paint();   //表刻度
    private Paint mPaint3 = new Paint();   //表时针
    private Paint mPaint4 = new Paint();   //表秒针
    private WindowManager mWM;
    private int time = 0;
    private int hour = 0;

    public CustomView(Context context) {
        super(context);
        mPaint1.setStyle(Paint.Style.STROKE);
        mPaint1.setStrokeWidth(5);
        mPaint1.setAntiAlias(false);
        mPaint3.setStrokeWidth(20);
        mPaint4.setStrokeWidth(10);
        setValues();
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint1.setStyle(Paint.Style.STROKE);
        mPaint1.setStrokeWidth(5);
        mPaint1.setAntiAlias(false);
        mPaint3.setStrokeWidth(20);
        mPaint4.setStrokeWidth(10);
        setValues();
    }

    private void setValues() {
        mWM = (WindowManager) getContext()
                .getSystemService(Context.WINDOW_SERVICE);
        mLength = mWM.getDefaultDisplay().getWidth();
        mCircleXY = mLength / 2;
        mRadius = (float) (mLength * 0.5);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制钟表外圈圆环
        canvas.drawCircle(mCircleXY, mCircleXY, mRadius-20, mPaint1);
        //消除锯齿
        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG
                | Paint.FILTER_BITMAP_FLAG));
        for (int i = 0; i < 60; i++) {
            //通过旋转坐标系绘制刻度
            String degree = String.valueOf(i / 5);
            if (i % 15 == 0) {
                mPaint2.setStrokeWidth(5);
                mPaint2.setTextSize(30);
                canvas.drawLine(mCircleXY, 20, mCircleXY, 80, mPaint2);
                if (i == 0) {
                    canvas.drawText("12", mCircleXY - mPaint2.measureText(degree) / 2, 120, mPaint2);
                } else {
                    canvas.drawText(degree, mCircleXY - mPaint2.measureText(degree) / 2, 120, mPaint2);
                }
            } else if (i % 5 == 0) {
                mPaint2.setStrokeWidth(5);
                mPaint2.setTextSize(30);
                canvas.drawLine(mCircleXY, 20, mCircleXY,60, mPaint2);
                canvas.drawText(degree, mCircleXY - mPaint2.measureText(degree) / 2, 100, mPaint2);
            } else {
                mPaint2.setStrokeWidth(5);
                mPaint2.setTextSize(30);
                canvas.drawLine(mCircleXY, 20, mCircleXY, 40, mPaint2);
            }
            canvas.rotate(6, mCircleXY, mCircleXY);
        }

        //平移坐标系,绘制时针
        canvas.translate(mCircleXY, mCircleXY);
        canvas.drawLine(0, 0, 100, 100, mPaint3);

        //旋转坐标系,绘制分针
        canvas.rotate(6 * time, 0, 0);
        canvas.drawLine(0, 0, 100, 200, mPaint4);

        time++;
        postInvalidateDelayed(1000);
    }

}

  这样就可以绘制出图中所示的表盘,源码的链接:https://github.com/jiushi555/CustomView/tree/master/CustomTimepiece。

  转载请标明出处。

时间: 2024-10-09 18:48:16

自定义view(二)的相关文章

自定义View(二)(Android群英传)

内容是博主照着书敲出来的,博主码字挺辛苦的,转载请注明出处,后序内容陆续会码出. 上一篇自定义View(一)(Android群英传)中说的是对现有控件进行拓展,这篇介绍第二种自定义View方法,创建复合控件. 创建复合控件 创建复合控件可以很好地创建出具有重用功能的控件集合.这种方式通常需要继承一个合适的ViewGroup,再给它添加指定功能的控件,从而组合成新的复合控件.通过这种方式创建的控件,我们一般会给它指定一些可配置的属性,让它具有更强的拓展性.下面就以一个TopBar为示例,讲解如何创

Android 自定义View (二) 圆环交替 等待效果

我们在下载的时候需要一个下载的进度,而且可能产品要一个漂亮的界面,而不是android自带的进度条了,在这感谢http://blog.csdn.net/lmj623565791/article/details/24500107博客的无私奉献 废话不多说,直接切入主题 先新建一个android项目:CustomProgressBar 还记得自定义view的步骤么 1.自定义View的属性 2.在View的构造方法中获得我们自定义的属性 [ 3.重写onMesure ] 4.重写onDraw A:

自定义View(二)--继承自ViewGroup

自定义View包括很多种,上一次随笔中的那一种是完全继承自View,这次写的这个小Demo是继承自ViewGroup的,主要是将自定义View继承自ViewGroup的这个流程来梳理一下,这次的Demo中自定义了一个布局的效果,并且这个自定义布局中包含布局自己的属性,布局中的控件也包含只属于这个布局才具有的自定义属性(类似于layout_weight只存在于LinearLayout中,只有LinearLayout中的控件可以使用一样).话不多说,先看效果图: 其中红色的部分是自定义的ViewGr

自定义View(二),强大的Canvas

本文转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html Android中使用图形处理引擎,2D部分是android SDK内部自己提供,3D部分是用Open GL ES 1.0.今天我们主要要了解的是2D相关的,如果你想看3D的话那么可以跳过这篇文章. 大部分2D使用的api都在android.graphics和android.graphics.drawable包中.他们提供了图形处理相关的: C

Android 自定义View (二) 进阶

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24300125 继续自定义View之旅,前面已经介绍过一个自定义View的基础的例子,Android 自定义View (一),如果你还对自定义View不了解可以去看看.今天给大家带来一个稍微复杂点的例子. 自定义View显示一张图片,下面包含图片的文本介绍,类似相片介绍什么的,不过不重要,主要是学习自定义View的用法么. 还记得上一篇讲的4个步骤么: 1.自定义View的属性2

Android自定义view学习笔记02

Android自定义view学习笔记02 本文代码来自于张鸿洋老师的博客之Android 自定义View (二) 进阶 学习笔记,对代码进行些许修改,并补充一些在coding过程中遇到的问题.学习的新东西. 相关代码 //CustomImageView.java package mmrx.com.myuserdefinedview.textview; import android.content.Context; import android.content.res.TypedArray; im

Android自定义View(二)

前言 魅族手机的闹钟应用中有个倒计时,这个控件还是蛮有趣的.左边是魅族闹钟,右边是我们最终实现的效果,虽然有些细节还需优化,不过基本上已经达到了想要的效果,我们先来就来看看如何实现吧. 分析 确定宽高 对一个Android自定义控件来说,一般都经过三个步骤 onLayout() onMeasure() onDraw() onLayout明确子控件在父控件中的位置(本控件不需要重写),onMeasure是确定控件的大小(宽.高),而onDraw是我们重点关注的方法,我们需要在这个方法中写入显示Vi

Android软件开发之盘点自定义View界面大合集(二)

Android软件开发之盘点自定义View界面大合集(二) - 雨松MOMO的程序世界 - 51CTO技术博客 雨松MOMO带大家盘点Android 中的自定义View界面的绘制 今天我用自己写的一个Demo 和大家详细介绍一个Android中自定义View中的使用与绘制技巧. 1.自定义view绘制字符串 相信在实际开发过程中必然很多地方都须要用到系统字 为什么会用到系统字? 方便 省内存 我相信做过J2ME游戏开发的朋友应该深知内存有多么多么重要 而且使用它还可以带来一个更重要的好处就是很方

Android进阶之自定义View实战(二)九宫格手势解锁实现

一.引言 在上篇博客Android进阶之自定义View实战(一)仿iOS UISwitch控件实现中我们主要介绍了自定义View的最基本的实现方法.作为自定义View的入门篇,仅仅介绍了Canvas的基本使用方法,而对用户交互层面仅仅处理了单击事件接口,在实际的业务中,常常涉及到手势操作,本篇博客以九宫格手势解锁View为例,来说明自定义View如何根据需求处理用户的手势操作.虽然九宫格手势解锁自定义View网上资料有很多,实现原理大同小异,但这里我只是根据自己觉得最优的思路来实现它,目的是让更