自定义View
自定义View即系统中没有的,我们自己实现的View,一般继承自View
自定义有四个构造函数,其中前三个构造函数
public class CustomView extends View {
// 代码中直接new的时候调用
public CustomView(Context context) {
super(context);
}
// xml布局中使用的时候调用
public CustomView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
// xml布局中使用,并且xml布局中包含style属性的时候调用
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
// xml布局中使用,并且第三个参数为0的时候调用
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
}
onMeasure()
/**
* MeasureSpec.AT_MOST : 在布局中指定了wrap_content
* MeasureSpec.EXACTLY : 在布局中指定了确切的值\match_parent\fill_parent
* MeasureSpec.UNSPECIFIED : 尽可能地大,很少能用到
*
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 获取宽高的模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
}
ScrollView嵌套ListView会布局显示不全地原因就是因为ScrollView传入子View地测量模式为MeasureSpec.UNSPECIFIED
,而ListView中测量所有子View地高度所需要地测量模式为MeasureSpec.AT_MOST
,具体看源码:
可以看出ListView中只计算一个高度,可重写ListView地onMeasure方法解决
public class MyListView extends ListView {
public MyListView(Context context) {
super(context);
}
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
其中为什么要传值为Integer.MAX_VALUE >> 2
,那是因为这里,具体可看源码ListView#measureHeightOfChildren