如何自定义控件主要分为以下几个步骤:

1、自定义属性的声明与获取

(1)分析需要的自定义属性

(2)在res/values/attrs.xml定义声明,如

<resources>

    <declare-styleable name="HookView">
        <attr name="loadingText" format="string" />
        <attr name="completeText" format="string" />
        <attr name="textSize" format="dimension" />
    </declare-styleable>

</resources>

(3)在layout xml文件中进行使用

定义了名称然后3个属性,然后在自定义控件引用时候加上

    xmlns:app="http://schemas.android.com/apk/res-auto"

然后使用app:loadingText = “string”设置所要配置的属性

(4)在view的构造方法中进行获取

在自定义控件中利用TypedArray获取所设置的属性

if (attrs != null) {
            //获取自定义属性
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.HookView);
            if (ta.hasValue(R.styleable.HookView_loadingText))
                loadingText = ta.getString(R.styleable.HookView_loadingText);
            if (ta.hasValue(R.styleable.HookView_completeText))
                completeText = ta.getString(R.styleable.HookView_completeText);
            textSize = ta.getDimension(R.styleable.HookView_textSize, 20);
            ta.recycle();
        }

这里使用完记得recycle(),这是由于自定义View,会随着 Activity的每一次Create而Create,因此,需要系统频繁的创建array,对内存和性能是一个不小的开销,如果不使用池模式,每次都让GC来回收,很可能就会造成OutOfMemory,程序在运行时维护了一个 TypedArray的池,程序调用时,会向该池中请求一个实例,用完之后,调用 recycle() 方法来释放该实例,从而使其可被其他模块复用,记得使用完调用recycle()就好。

2、测量onMewsure(占多大空间)

通常View在屏幕上显示出来要先经过measure然后到layout. 在调用onMeasure(int widthSpec, int heightSpec)方法时,要涉及到MeasureSpec的使用

MeasureSpec有3种模式分别是【UNSPECIFIED】 、【EXACTLY】、【AT_MOST】

当我们设置width或height为fill_parent时,容器在布局时调用子 view的measure方法传入的模式是EXACTLY,因为子view会占据剩余容器的空间,所以它大小是确定的。

而当设置为 wrap_content时,容器传进去的是AT_MOST, 表示子view的大小最多是多少,这样子view会根据这个上限来设置自己的尺寸。当子view的大小设置为精确值时,容器传入的是EXACTLY, 而MeasureSpec的UNSPECIFIED模式通常是滑动控件中给子控件View的onMeasure方法默认行为是当模式为UNSPECIFIED时,设置尺寸为mMinWidth(通常为0)或者背景drawable的最小尺寸。

形象的说来,onMeasure方法在父元素正要放置该控件时调用.父控件调用它向子控件问一个问题,“你想要用多大地方啊?”,然后传入两个参数——widthMeasureSpec和heightMeasureSpec.它们指明控件可获得的空间以及关于这个空间描述的元数据.比返回一个结果要好的方法是你传递View的高度和宽度到setMeasuredDimension方法里.

下面看一下经典的View中onMeasure实现

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int measuredHeight = measureHeight(heightMeasureSpec);

int measuredWidth = measureWidth(widthMeasureSpec);

setMeasuredDimension(measuredHeight, measuredWidth);

}

private int measureHeight(int measureSpec) {

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

// Default size if no limits are specified.

int result = 500;

if (specMode == MeasureSpec.AT_MOST){

// Calculate the ideal size of your

// control within this maximum size.

// If your control fills the available

// space return the outer bound.

result = specSize;

}
else if (specMode == MeasureSpec.EXACTLY){

// If your control can fit within these bounds return that value.

result = specSize;

}

return result;

}

private int measureWidth(int measureSpec) {

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

// Default size if no limits are specified.

int result = 500;

if (specMode == MeasureSpec.AT_MOST){

// Calculate the ideal size of your control

// within this maximum size.

// If your control fills the available space

// return the outer bound.

result = specSize;

} 

else if (specMode == MeasureSpec.EXACTLY){

// If your control can fit within these bounds return that value.

result = specSize;

}

return result;

}

关于MeasureSpec类这里多说一点,

它代表一个32位的int值,高2位代表specMode(测量模式),低30位代表specsize(某种测量模式下的规格大小)

关于它的常用三个函数:

static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)

static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)

static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)

3、布局onLayout(放在什么位置)

4、绘制onDraw(绘制什么)

通常需要熟练掌握 canvas、Path的API,可能还有属性动画的交互

5、onTouchEvent

需要做用户交互,对Event事件的捕捉处理

6、onInterceptTouchEvent(viewgroup)

viewgroup中事件拦截,这里需要掌握事件分发机制

入门主要是这几块内容,每一块都需要深入理解,在看到一个自定义view源码时往往就是通过这几块往下分析

自定义view入门的更多相关文章

  1. Android简易实战教程--第二十七话《自定义View入门案例之开关按钮详细分析》

    转载此博客请注明出处点击打开链接       http://blog.csdn.net/qq_32059827/article/details/52444145 对于自定义view,可能是一个比较大的 ...

  2. Android自定义View入门(一)

    最近在写一个关于音乐播放的应用,写到播放界面UI时,就想自己实现的一个播放界面.那么如何实现自定义View呢?通过查看他人博客和Android官方开发文档,初步了解了一些浅显的内容.在此记录,已供需要 ...

  3. 自定义View入门-绘制基础(1)

    ### 前言 说道自定义View,我们一定会想到,自定义View的绘制流程 - 测量阶段(measure) - 布局阶段(layout) - 绘制阶段(draw) 我们看到的一些炫酷的view效果,都 ...

  4. 1.自定义view入门

    1.继承自view 系统提供的view 如 TextView .ImageView 都是继承自view的: 2.自定义一个TextView 通过自定义一个TextView 来熟悉继承自view 的自定 ...

  5. Android之自定义View的实现

    对于学习Android开发的小童鞋对于自定义View一定不会陌生,相信大家对它是又爱又恨,爱它可以跟随我们的心意设计出漂亮的效果:恨它想要完全流畅掌握,需要一定的功夫.对于初学者来说确实很不容易,网上 ...

  6. Android自定义View

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901 很多的Android入门程序猿来说对于Android自定义View ...

  7. Android 自定义View (一)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901 很多的Android入门程序猿来说对于Android自定义View ...

  8. Android 自定义View(button)

    很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章.先总结下自定义View的步骤 ...

  9. 推翻自己和过往,重学自定义View

    http://blog.csdn.net/lfdfhl/article/details/51671038 深入探讨Android异步精髓Handler 站在源码的肩膀上全解Scroller工作机制 A ...

随机推荐

  1. GIF动态图制作

    GIF动态图制作 博客写了也有一阵了,一直好奇大牛的博客里demo的动态图是怎么做的,今天抽空研究了一下,找了一个软件,以后再发现有好的工具再继续推荐 GIF制作工具--LICEcap 效果要比下面的 ...

  2. SceneKit:简单的3D游戏场景搭建

    SceneKit是Apple用来开发休闲3D游戏的框架,不同于底层的OpenGL库,你仅仅需要很少的代码就可以快速看到实际的3D场景效果.下面简单的聊聊搭建一个3D游戏场景需要做的事情. 首先你必须用 ...

  3. iOS开发之UIWebView的常见一些用法

    虽然现在Xcode8已经开始使用WKWebView这个框架进行网页展示,但是UIWebView也有一些常用的方法需要知道,下面就简单展示一下,仅供大家参考 相关知识:1.设置背景透明:2.加载本地HT ...

  4. EJB开发第一个无状态会话bean、开发EJB客户端

    开发第一个无状态会话bean EJB中的三中bean: 会话Bean(Session Bean) 负责与客户端交互,是编写业务逻辑的地方,在会话bean中可以通过JDBC直接操作数据库,但大多数情况下 ...

  5. linuxsvn源代码版本库建立

    linuxsvn源代码版本库建立 下面就要建立代码的版本库做描述: 1.     安装svn版本服务器端 yum install subversion 从镜像下载安装svn服务器端,我们服务器已经安装 ...

  6. Android之Animation动画的使用(一)

    我们在使用一些控件时候,难免会设置一些进入和退出的动画效果,比如popupwindow.listview的item动画.按钮.图片等等,要使这些控件有动画效果,当然需要用到Animation了. 下面 ...

  7. SSH框架实现仿淘宝购物demo

    还记得六月份实习的时候,曾经做过一个电商的项目,项目里面需要实现类似淘宝购物车的移动端的demo,随着项目的进行,再一次跟购物车碰面,但是今天呢,不是移动端的需求,如何使用SSH框架实现类似淘宝的购物 ...

  8. 【java虚拟机序列】java中的垃圾回收与内存分配策略

    在[java虚拟机系列]java虚拟机系列之JVM总述中我们已经详细讲解过java中的内存模型,了解了关于JVM中内存管理的基本知识,接下来本博客将带领大家了解java中的垃圾回收与内存分配策略. 垃 ...

  9. Android项目开发填坑记-Fragment的onAttach

    背景 现在Android开发多使用一个Activity管理多个Fragment进行开发,不免需要两者相互传递数据,一般是给Fragment添加回调接口,让Activity继承并实现. 回调接口一般都写 ...

  10. [django]用日期来查询datetime类型字段

    有一个model的字段是 DateTimeField,我现在要具体查询某一天date的数据,应该怎么用orm来查询呢? 指定年月日 YourModel.objects.filter(datetime_ ...