自定义view onLayout
measure过程结束后,视图测量完毕,就需要进行layout过程。layout过程源码如下
public void layout(int l, int t, int r, int b) {
int oldL = mLeft;
int oldT = mTop;
int oldB = mBottom;
int oldR = mRight;
boolean changed = setFrame(l, t, r, b);
if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
if (ViewDebug.TRACE_HIERARCHY) {
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
}
onLayout(changed, l, t, r, b);
mPrivateFlags &= ~LAYOUT_REQUIRED;
if (mOnLayoutChangeListeners != null) {
ArrayList<OnLayoutChangeListener> listenersCopy =
(ArrayList<OnLayoutChangeListener>) mOnLayoutChangeListeners.clone();
int numListeners = listenersCopy.size();
for (int i = 0; i < numListeners; ++i) {
listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
}
}
}
mPrivateFlags &= ~FORCE_LAYOUT;
}
在上面的layout方法中,首先通过传入的l, t, r, b进行判断是否需要重绘,我们也知道如果view的布局并没有发生变化,就不需要进行再一次的重新计算布局。在上面的代码中还可以看到调用了onLayout方法,这也就是我们经常需要重写的方法。在onLayout方法中我们可以根据自己的需要进行对子view的布局操作。
而如果是view的onLayout则经常直接调用super方法,不需要对其进行操作。
@Override
protected abstract void onLayout(boolean changed,int l, int t, int r, int b);
传入l t r b分别代表相对于父布局的左边距,上边距,右边距和下边距。
当我们重写viewGroup时候,需要对onLayout进行重写,从而判定得到子view的摆放方式,通过调用子view的layout方法,传入计算好的 l, t,r,b即可。
“`
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 获得子View个数
int childCount = getChildCount();
// 父View左侧的距离
int mLeft = 0;
// 遍历子View
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
// 获得子View的高度
int childViewHeight = childView.getMeasuredHeight();
// 获得子View的宽度
int childViewWidth = childView.getMeasuredWidth();
// 让子View在竖直方向上显示在屏幕的中间位置
int height = sreenH / 2 - childViewHeight / 2;
// 调用layout给每一个子View设定位置mLeft,mTop,mRight,mBottom.左上右下
childView.layout(mLeft, height, mLeft + childViewWidth, height
+ childViewHeight);
// 改变下一个子View到父View左侧的距离
mLeft += childViewWidth;
}
}
一个简单的demo实现简单的横向排列效果