自定义view入门
如何自定义控件主要分为以下几个步骤:
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入门的更多相关文章
- Android简易实战教程--第二十七话《自定义View入门案例之开关按钮详细分析》
转载此博客请注明出处点击打开链接 http://blog.csdn.net/qq_32059827/article/details/52444145 对于自定义view,可能是一个比较大的 ...
- Android自定义View入门(一)
最近在写一个关于音乐播放的应用,写到播放界面UI时,就想自己实现的一个播放界面.那么如何实现自定义View呢?通过查看他人博客和Android官方开发文档,初步了解了一些浅显的内容.在此记录,已供需要 ...
- 自定义View入门-绘制基础(1)
### 前言 说道自定义View,我们一定会想到,自定义View的绘制流程 - 测量阶段(measure) - 布局阶段(layout) - 绘制阶段(draw) 我们看到的一些炫酷的view效果,都 ...
- 1.自定义view入门
1.继承自view 系统提供的view 如 TextView .ImageView 都是继承自view的: 2.自定义一个TextView 通过自定义一个TextView 来熟悉继承自view 的自定 ...
- Android之自定义View的实现
对于学习Android开发的小童鞋对于自定义View一定不会陌生,相信大家对它是又爱又恨,爱它可以跟随我们的心意设计出漂亮的效果:恨它想要完全流畅掌握,需要一定的功夫.对于初学者来说确实很不容易,网上 ...
- Android自定义View
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901 很多的Android入门程序猿来说对于Android自定义View ...
- Android 自定义View (一)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901 很多的Android入门程序猿来说对于Android自定义View ...
- Android 自定义View(button)
很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章.先总结下自定义View的步骤 ...
- 推翻自己和过往,重学自定义View
http://blog.csdn.net/lfdfhl/article/details/51671038 深入探讨Android异步精髓Handler 站在源码的肩膀上全解Scroller工作机制 A ...
随机推荐
- Angular2入坑指南
序 对后端开发来说,前端是神秘的,眼花缭乱的技术,繁多的框架,出名的不出名的好几百种,看是"繁荣",其实显得杂乱无章,但是我们在做开发的时候,技术选型还是主流的那么几个:浅析ang ...
- 自制Linux重命名命令
相比于Windows上的ren命名,Linux还真的是没有一个特定的重命名的命令.(虽然可以间接的使用mv来实现).下面我就来自己写一个简单的重命名命令. 准备工作 操作系统: Linux内核的系统都 ...
- [ExtJS5学习笔记]第三十节 sencha extjs 5表格gridpanel分组汇总
本文地址:http://blog.csdn.net/sushengmiyan/article/details/42240531 本文作者:sushengmiyan ------------------ ...
- Android必知必会-获取View坐标和长宽的时机
如果移动端访问不佳,请访问–>Github版 背景 最近要实现一个功能,用到了一些属性动画,需要获取一些View的坐标信息,设计图如下: 这里我使用的是DialogFragment来实现的,可以 ...
- tf.app.run()
在很多TensorFlow公布的Demo中,都有这样的代码存在,如下,这是干什么的呢? if __name__ == "__main__": tf.app.run() 我们来看一下 ...
- API创建员工Element
DECLARE ln_element_link_id PAY_ELEMENT_LINKS_F.ELEMENT_LINK_ID%TYPE; ld_effective_start_date DATE; l ...
- 【VSTS 日志 15/11/18】 – 插件应用市场,RM,包管理器等
[小编]从今天开始,我将在这个博客上连载Visual Studio Team Service的定期更新.VSTS是Team Foundation Server 的在线版本,微软每3周会对这个服务进行更 ...
- Linux:ssh_config快速访问服务器
在当前用户的根目录下: cd ~/.ssh vi config 编辑config内容为下面: ForwardAgent yes Host 1 Hostname 192.168.1.1 User roo ...
- 【Unity Shaders】Transparency —— 使用渲染队列进行深度排序
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- eclipse new server Cannot create a server using the selected type 网上有两种办法,其实原理一样
eclipse new server Cannot create a server using the selected type 网上有两种办法,其实原理一样 第一种说法: 还真的找到解决的方法了, ...