前言
自定义View的内容不光有绘制,还有布局,而且绘制是去调用已知的API,而布局就得需要我们去理解它内部的工作原理才能正确的去使用它,我们来总结一下吧
基本原理
// 测量阶段
// 从顶层的根View开始去测量和布局
// 子View的measure()方法会被父View调用, 然后最调用onMearsure(), 让View进行自我测量
// 如果子View仅仅是一个View, 没有子View, 那么它仅仅计算出自己的尺寸, 然后保存
// 如果子View也是一个ViewGroup, 重复上面的测量步骤, 根据所有子View计算出自己的尺寸
// 布局阶段
// 子view的layout()方法会被父view调用, 会将子View的尺寸和位置当做参数传入
// 子view自己调用onLayout()方法, 进行自我布局
// 如果此子view是一个ViewGroup, 还会继续调用它子View的layout()方法
// 如果此子view仅仅是一个view, 那么onLayout()方法是什么也不用干的
布局自定义的方式
// 1 重写onMeasure()来修改已有的View的尺寸
// 2 重写onMeasure()来全新定制自定义View的尺寸
// 3 重写onMeasure()和onLayout()来全新定制自定义ViewGroup的内部布局
第一类onMeasure()的做法:
// 重写onMeasure()方法, 并调用super.onMeasure(), 触发原有的自我测量
// 用getMeasureWidth()和getMeasureHeight()来获取之前的测量结果
// 根据获取的测量结果, 计算出新的计算结果
// 调用setMeasureDimension()来保存新的结果
总结
这一小节其实就是理论偏多,理解基本的概念,mode和size等概念还没有提及。
贴一个HenCoder的链接:自定义View-布局基础
实践
// 修改ImageView 使它的宽和高一样
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
if (measuredWidth > measuredHeight) {
measuredWidth = measuredHeight;
} else {
measuredHeight = measuredWidth;
}
setMeasuredDimension(measuredWidth, measuredHeight);
}