1. 综述:
自定义容器控件或view控件,使用到的方法:onMeasure(), measure, setMeasuredDimension(), onLayout(), layout()等
自定义容器控件(布局器),一般是继承ViewGroup或其子类XyyLayout(LinearLayout),必须重写的方法有:
(1)自定义容器控件的构造函数,因为无论是从xml中加载该自定义容器控件,还是直接在java代码中加载,都要调用构造函数;
(2)onMeasure(),这里这个请格外注意,这个必须有,因为我们自定义的是一个容器,容器肯定会在xml中包含View控件,而这些子View控件必须得由父控件(这里是指自定义的容器控件)来指定大小尺寸;
(3)onLayout(),这个也必须有,因为父容器控件负责布局其子View控件;
(4)onDraw(),这个可有可无,当需要自己重画自定义控件的时候,才需要重写改方法;
下面是根据具体需求来决定是否需要重写的方法:
(5)computeScroll(),如果需要对手势的滚动进行处理,而且使用了Scroller来处理滚动,则需要重写这个方法,Scroller的方法是个滚动辅助类,本身的方法不会对View或ViewGroup进行真实物理的滚动,但他们的操作(如:startScroll()等),再加上invalide()方法,则会触发computeScroll()方法的执行;这个方法才是真实的滚动;
(6)onTouchEvent(),如果需要对触摸手势进行操作,这个方法是必须重写的。
(7)onInterceptTouchEvent(),即使是需要对触摸手势进行处理,这个方法也不一定需要重写,这个方法和onTouchEvent()都是根据其返回值来决定是否需要传递触摸事件;关于onInterceptTouchEvent()和onTouchEvent()传递事件请查看:
http://blog.csdn.net/habbyge/article/details/16860041
针对自定义控件的时候,支持触摸事件,我们需要用到Scroller类和View本身的scrollTo()/scrollBy(),还有invalidate()方法,其中scrolleTo()/scrolleBy()/invalide()是真实物理上的滚动操作。注意:Scroller的滚动方向和手指触摸的方向是相反的,在设置中应该注意!!
注:另外需要注意的是重写ViewGroup等布局器(LinearLayout),与重写ListView等是不同的,虽然ListView也是ViewGroup的子类,但是ListView一般是被当成单独的控件存在的,也就是说自定义更特殊的ListView的时候,不必按照本文的方法来自定义,只需要按照继承View的方法即可,当然有需求的话,也可按照本文的方法来重写;
2. 例子:
支持左右滑动View的ViewGroup(布局器)
另外一个讲手势、触摸、滚动比较好的是:
http://mobile.51cto.com/design-375889.htm
http://blog.csdn.net/xyz_lmn/article/details/16826669
这个链接对MeasureSpec的三种尺寸模式(AT_MOST EXACTLY UNSPECTED)有解释:
http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html
讲onMeasure()方法链接:http://www.cppblog.com/guojingjia2006/archive/2012/03/27/169214.html
其实学习自定义控件最好的例子是源代码。注:onMeasure()的传入的父控件希望的子控件的宽高,其实是个复合型的,是32bit的int值,高2位代表Mode,剩下代表size。