自定义View概述
1.自定义View分类
- 自定义View 直接继承View主要是绘制
- 自定义ViewGroup 继承ViewGroup主要是计算所有子控件的大小和位置
- 继承相应的View,如TextView,Button,LinearLayout等
2.自定义View的流程
自定义view的绘制流程3.相应的构造函数:
当你继承View会有4个相应的构造方法:
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对象的时候调用的方法
- 第二个是在布局文件中使用的时候调用的方法
- 第三个是设置主题的时候调用的方法,这里你可以指定,也可以写死
- 第四个是在21版本新添加的方法,暂且不论
4.View的测量(onMeasure)
这个方法的作用是用来测量View的相应的方法,基本上有固定的模板代码,其实就是计算整个View占用的大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int realWidth;/*真是的宽度*/
int realHeight;/*真是的高度*/
if (widthMode == MeasureSpec.EXACTLY) {
realWidth = width;
} else if (widthMode == MeasureSpec.AT_MOST) {
realWidth = 500;/*这里是定义的最大值*/
} else {
realWidth = 500;/*未知宽度的时候*/
}
if (heightMode == MeasureSpec.EXACTLY) {
realHeight = height;
} else if (heightMode == MeasureSpec.AT_MOST) {
realHeight = 500;/*这里是定义的最大值*/
} else {
realHeight = 500;/*未知高度的时候*/
}
setMeasuredDimension(realWidth, realHeight);
}
这里记住相应的三种状态:
- AT_MOST 最大值,但是不会超过父容器
- EXACTLY 具体指,指定了具体的大小
- UNSPECIFIED 未知大小,这里是父容器没有指定相应的大小(其实上面的两种状态考虑到的话就可以不用去设置这个了)
上面这个例子基本上就是onMeasure的模板代码,但是有的控件涉及到重绘界面,那么只要把相应的realWidth和realHeight写成动态的就可以了.但是基本的逻辑是不会改变的...
5.View的绘制(onDraw)
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
这个方法主要涉及到Canvas的相应操作,后面会单提出来去讲.其实就是相应的API的一些绘制操作.
6.View大小的改变操作(onSizeChanged)
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
其实这个方法是确定View大小的方法,但是如果你调用** requestLayout();**方法的时候是强制重绘,整个绘制流程都会重新走一遍,也就是说onMeasue(),onSizeChanged()和onDraw()都会重新执行,这样也就达到了相应的改变View的效果了,这种一般都是和手势有关的View.
7.子View位置的确定(onLayout)
确定布局的函数是onLayout,它用于确定子View的位置,在自定义ViewGroup中会用到,他调用的是子View的layout函数。
View位置的确定
其实这里面只有一张图的事情,理解了这张图就能更好的设置相应的位置了.
8.相应的属性值
其实这部分的代码也是相应的模板代码,只要记住了就行.
- 在相应的res文件夹下创建一个attrs的xml文件,用来实现自定义View的style(也就是可以使用的属性)
<declare-styleable name="HorizontalEditItemView"> <attr name="title" format="string" /> <attr name="etHint" format="string" /> </declare-styleable>
这里的属性你可以随意定义,只要符合你的习惯就行
- 在自定义View中使用该属性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HorizontalEditItemView); String title = typedArray.getString(R.styleable.HorizontalEditItemView_title); String etHint = typedArray.getString(R.styleable.HorizontalEditItemView_etHint); typedArray.recycle();
这里使用完TypedArray之后一定要进行释放.
概述的内容就这么多,其实写的挺晦涩的,这里讲的太仔细的话,效果还是一样的,只有你真正的去使用,才能去理解.这里只是一个概述,后面的文章会在使用的时候更加完善的讲解!
网友评论