カスタムビューでは、ビューを描画するために、onLayout、onDraw、dispatchDrawの3つの関数を書き直すことができます。
これら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メソッドが再度呼び出されます。
ビューのレイアウト方法では、親レイアウトでのビューの位置を定義できます。