在自定义视图中,可重写3个函数用于视图的绘制,分别是onLayout,onDraw和dispatchDraw。
这3个函数的执行顺序是onLayout → onDraw → dispatchDraw。
onLayout方法用于定位子视图在本布局视图中的位置。
该方法的入参表示本布局在上级视图的上,下,左,右位置。
实现方法如下
public class OffsetLayout extends RelativeLayout {
private int mOffsetHorizontal = 0;//水平方向的偏移量
private int mOffsetVertical = 0;//垂直方向的偏移量
public OffsetLayout(Context context) {
super(context);
}
public OffsetLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public OffsetLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child.getVisibility()!=GONE){
//计算子视图的左偏移量
int new_left = (r-l)/2 - child.getMeasuredWidth()/2 + mOffsetHorizontal;
//计算子视图的上方偏移量
int new_top = (b-t)/2 - child.getMeasuredHeight()/2 + mOffsetVertical;
//根据最新的上下左右四周边界,重新放置该子视图
child.layout(new_left,new_top,new_left+child.getMeasuredWidth(),new_top+child.getMeasuredHeight());
}
}
}
/**
* 设置水平方向上的偏移量
* @param offset
*/
public void setOffsetHorizontal(int offset){
mOffsetHorizontal = offset;
mOffsetVertical = 0;
//请求重新布局,此时会出发onLayout方法
requestLayout();
}
/**
* 设置垂直方向上的偏移量
* @param offset
*/
public void setOffsetVertical(int offset){
mOffsetHorizontal = 0;
mOffsetVertical = offset;
//请求重新布局,此时会触发onLayout方法
requestLayout();
}
}
当我们请求requestLayout方法的时候,就会重新调用onLayout方法。
而View的layout方法可以定义View在父布局中的位置。