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

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. DragVideo,一种在播放视频时,可以任意拖拽的方案

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53638896 前言 项目已开源到 ...

  2. 高通开发笔记---yukon worknote

    点击打开链接 daily buildhttp://android-ci-platform.cnbj.sonyericsson.net/job/daily_build_jb-mr2-yukon/DL-C ...

  3. 网络爬虫框架Scrapy简介

    作者: 黄进(QQ:7149101) 一. 网络爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本:它是一个自动提取网页的程序,它为搜索引擎从万维 ...

  4. 大数据基础知识问答----hadoop篇

    handoop相关知识点 1.Hadoop是什么? Hadoop是一个由Apache基金会所开发的分布式系统基础架构.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力进行高速 ...

  5. 使用QGIS将文本坐标转换为矢量文件

    本文主要是说明如果使用QGIS将文本格式的点坐标转换为矢量文件(如shapefile格式). 所需工具:QGIS 所需数据:文本格式的点文件 所需要处理的点坐标文件如下所示, 114.2 22.15 ...

  6. SpriteKit中类似Cocos2D的CCActionSpawn并发方法GroupAction

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我们知道在Cocos2D中对于并发Action的处理可以使用C ...

  7. [Vim]新建python文件自动添加python header

    使用vim脚本来实现的,使用了模板,几行代码就能实现很实用. ~/.vimrc 中的代码 "auto add pyhton header --start autocmd BufNewFile ...

  8. Ubuntu下装QQ2014(http://my.oschina.net/oscfox/blog/315951)

    QQ登陆界面: QQ登陆之后: 1.首先我们需要下载一个 deb的 Wine QQ安装包 qq2014官方下载:http://www.longene.org/download/WineQQ2013SP ...

  9. android 选项卡TabHost

    选项卡主要有TabHost.TabWiget和 FramentLayout3个组件组成,用于实现一个多标签的用户界面,通过他可以将一个复杂的对话分隔成若干个标签页,实现对信息的分类显示和管理.使用给组 ...

  10. Microsoft Dynamics CRM2011 更换Logo

    之前操作过但没做过记录,这里记录下以防以后有需要时记不起来还有迹可循 IE收藏栏的图标,在网站根目录下的的/favicon.ico CRM网页中的Logo,替换/_imgs/crmmastheadlo ...