自定义View
View常见的回调方式:
构造方法:(比较常见,经常通过构造方法完成初始化对象等操作);
onVisibilityChanged: 自定义view里面提供了一个状态模式的实现,允许在View 的visibility 发生改变时,引发执行onVisibilityChanged 方法中的动作。
onAttach(Activity):当Fragment与Activity发生关联时调用实现方式:
(1).继承View,重写onDraw方法.具体过程:measure-draw.
需注意:在onMeasure()里面,对wrap_content的支持,主要是MeasureSpec.AT_MOST和MeasureSpec.EXACTLY这两个情况的判定赋值,在onDraw()里面,对padding的支持,主要是getpaddingleft\bottom\top\right等判断;(2).继承ViewGroup派生特殊的Layout,具体过程:measure-layout,相关滑动\事件拦截的综合应用.
需注意:measure过程,除了完成自己的measure以外,还需要去遍历调用所有子元素的measure方法–取出子元素的layoutparams来创建MeasureSpec.再进行高度和宽度的叠加.(3),继承特点的View,例如:textView,EidtText等,可参考Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框 http://blog.csdn.net/xiaanming/article/details/11066685看源码.
(4)继承特定的ViewGroup,例如:LinearLayout\RelativeLayout.可参考自定义RelativeLayout实现Topbarhttp://download.csdn.net/detail/qq_28690547/9398303看源码.
常见注意事项:
(1).支持wrap_content,如上所述,onmeasure里面
(2).支持padding,如上所述,ondraw里面
(3).不要在View里面使用handler,直接用post
(4).在onAttachedToWindow()开始动画或启动线程;在onDetachedFromWindow()里面,停止动画和线程,经常使用
(5).View带滑动嵌套情形,需要处理好滑动冲突.- 绘制流程
(1).onMeasure(int widthMeasureSpec, int heightMeasureSpec),测量View的宽和高;标准代码:见书P186,P187
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == MeasureSpec.AT_MOST
&& heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(mWidth, mHeight);//mWidth,mHeight指定默认的内部高宽
} else if (widthSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(mWidth, heightSpecSize);
} else if (heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSpecSize, mHeight);
}
}
(2). onLayout(boolean changed, int left, int top, int right,int bottom),主要是调用子元素的view.layout(l, t, r, b)这个方法,去固定位置
(3). draw(Canvas canvas),主要是通过Paint将View绘制到屏幕上面.绘制过程:
①.绘制背景background.draw(canvas);
②.绘制自己onDraw();
③.绘制children(dispatchDraw);
④.绘制装饰(onDrawScrollBars);
SepcMode的含义:
UNPSECIFIED:父容器不对View有任何限制,要多大给多大,这种情况一般用于系统内部,表示一种测量状态,一般不考虑
EXACTLY:表示父容器检测出View所需要的精确大小,View的大小就是SpecSize所指定的值,一般对应match_parent和具体的数字
AT_MOST:表示View的大小不能超过这个父容器指定的值,一般应用于wrap_content;- 在Activity中去获取View的高度:
(1).Activity的onWindowFocusChanged(boolean hasFocus)中,通过getMeasureWidth()来获取View的高宽
(2).Activity的onStart()中,通过view.post去通过getMeasureWidth()来获取View的高宽
(3).这种方式也是我用的比较多的,使用OnGlobalLayoutListener接口,通过getViewTreeObserver同样通过getMeasureWidth()来获取View的高宽;
同章大牛笔记
http://hujiaweibujidao.github.io/blog/2015/12/01/Art-of-Android-Development-Reading-Notes-4/