其中onLayout()函数只有在自定义ViewGroup的时候才会用到
分类
自定义View分为两类:
自定义ViewGroup
自定义ViewGroup一般就是利用现有的组件根据特定的布局方式组成新的组件,大多继承ViewGroup或者是各种lauout。其中包含子控件
自定义View
在特定需求中,我们需要自己实现特定的控件,一般继承View,SurfaceView或者其他View。不包含子控件。
一般自定义View在大多数情况下都有替代方案,利用现有控件进行组合之类,但是这样可能对内存消耗会过大。
流程
1.构造函数
View的构造函数有四个,分别有一个,两个,三个,四个参数。
public void SloopView(Context context) {}
public void SloopView(Context context, AttributeSet attrs) {}
public void SloopView(Context context, AttributeSet attrs, int defStyleAttr) {}
public void SloopView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {}
有四个参数的不考虑,有三个参数的现在也不考虑。那就看有一两个参数的构造方法吧。
有一个参数的构造方法是在代码中new
的时候调用的。
这样回调用一个参数的构造函数。
SloopView view new SloopView(this);
当在布局文件中定义的时候就会调用两个参数的构造函数
<com.sloop.study.SloopView
android:layout_width"wrap_content"
android:layout_height"wrap_content"/>
2.测量View大小(onMeasure)
View的大小不仅由自身决定,还会受父控件影响,我们可以自己去测量并设定控件的大小。
测量View的大小使用的是onMesaure()函数:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthsize = MeasureSpec.getSize(widthMeasureSpec); //取出宽度的确切数值
int widthmode = MeasureSpec.getMode(widthMeasureSpec); //取出宽度的测量模式
int heightsize = MeasureSpec.getSize(heightMeasureSpec); //取出高度的确切数值
int heightmode = MeasureSpec.getMode(heightMeasureSpec); //取出高度的测量模式
}
确定一个控件的宽高有两部分组成,widthsize
和widthmode
用宽度举例widthMode
,测量模式有三种,被定义在View的内部类View.MeasureSpec中,
模式 | 描述 |
---|---|
UNSPECIFIED | 默认值,父控件没有给子空间任何限制,子空间可以设置为任意的大小 |
EXACTLY | 表示父控件已经确切的自定了子View的大小 |
AT_MOST | 表示子View具体大小没有尺寸限制,但是存在上限,上线一般为父View的大小 |
获取的方式上边代码中也写到了,用MeasureSpec的getSize获取数值,getMode获取模式
如果想对View的宽高进行修改,需要调用setMeasureDimension(widthSize,heightSize)这个函数,其中的参数就是修改后的宽高值。
3.确定View大小(onSizeChanged)
View大小有变化的时候,会调用这个方法,从这个方法中可以获取到新老宽高的值。
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//View最终的大小是w h
}
4.确定子View布局位置(onLayout)
这个方法用于确定子控件的位置,在自定义ViewGroup会用到,确定子控件的位置用的是子控件的layout函数
,也就是确定子控件的位置是在ouLayout()方法中循环去除子控件,然后通过计算得出每个子控件的位置坐标值,然后用每个子控件的layout方法进行位置确定。
child.layout(l, t, r, b);
参数值 | 对应函数 |
---|---|
l | getLeft(); |
t | getTop(); |
r | getRight(); |
b | getBottom(); |
5.绘制内容(onDraw)
onDraw()函数是事记的绘制的部分,使用canvas进行绘图
6.对外提供操作方法和监听回调
一般在OnTouchEvent()函数中点击事件进行处理,然后通过监听回调将事件传到外部进行处理。