学习android开发,我感觉自定义控件这个一定要好好的学习,这样能解决各式各样的需求。下面是我自己做的总结,写在这里方便以后复习吧。(看了好多的资料)
这里就先讲一下自定义View吧(感觉比较简单点相对于ViewGroup)
对于自定义View来说,就好像我们要在app上画一个自己想要的东西一样,先需要知道要画的东西的大小,然后进行绘制。
所以我们需要重写2个方法:
1.onMeasure()
2.onDraw()
onMeasure,就是测量,用来确定你想要View的大小,所以我们要重写View的onMeasure(),如下
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
虽然super.onMeasure()中会最终调用setMeasuredDimension()来为View设置宽高,但好像并不能正确的设置,所以需要我们自己亲自来设置比较靠谱
对于widthMeasureSpec,heightMeasureSpec这两个值我们可以用MeasureSpec对象将其拆分成Mode跟Size。Mode就是你在xml文件中对该控件的设置
match_parent or 精确值时(100dp) mode为EXACTLY
wrap_content 时 mode为 AT_MOST
于是,我们可以写个方法来准确测量传进来的widthMeasureSpec,heightMeasureSpec
/**
* 重新测量宽度
*
* @param widthMeasureSpec
* @return
*/
private int measureWidth(int widthMeasureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = windowWidth; //我们自己期望的View的大小
if (specMode == MeasureSpec.AT_MOST) {
result = Math.max(result, specSize);
}
}
return result;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取控件显示的高度宽度
width = measureWidth(widthMeasureSpec);
height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
}
测量好了之后就是绘制啦
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
这个就比较简单了,对着View的画板canvas随意的进行绘制就是啦
canvas.drawXXX()就行啦
这样一个自定义的View就做好啦
最后给一个大致的代码
java类
public class MyView extends View {
public MyScrollTableLeftTitle(Context context) {
this(context, null);
}
public MyScrollTableLeftTitle(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
height = measureHeight(heightMeasureSpec);
width = measureWidth(widthMeasureSpec);
setMeasuredDimension(width , height);
}
/**
* 重新测量高度
*
* @param heightMeasureSpec
* @return
*/
private int measureHeight(int heightMeasureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(heightMeasureSpec);
int specSize = MeasureSpec.getSize(heightMeasureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.max(result, specSize);
}
}
return result;
}
/**
* 重新测量宽度
*
* @param widthMeasureSpec
* @return
*/
private int measureWidth(int widthMeasureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = getBlocWidth(); //自己期望的宽度
if (specMode == MeasureSpec.AT_MOST) {
result = Math.max(result, specSize);
}
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//代码省略
}
}
xml里
<包名.MyView
android:layout_width="wrap_content"
android:layout_height="100dp" />