padding和margin
padding用于控制view內(nèi)容邊界與view邊界的距離對
- viewGroup用padding時,其作用于其子控件,控制子控件與該viewGroup的邊距
- view用padding時,控制view的內(nèi)容與view邊界的距離
margin用于控制本控件子控件與父控件的邊距 - viewGroup用margin時,其控制本viewGroup與其他view的邊距
- view用margin時,其控制本view與其他view的邊距
小結(jié)
從上面的現(xiàn)象可以得出:viewGroup設置padding作用于其子view時,相當于子view設置了margin
自定義viewGroup(包含margin,padding)
public class SwipeItemLayout extends ViewGroup {
public SwipeItemLayout(Context context) {
super(context);
}
public SwipeItemLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/**
*
* 測量子view的大小,也可以用measureChild,需要遍歷子view
* measureChildren內(nèi)部也是調(diào)用了measureChild方法
* measureChildWithMargins也是同理
*/
// measureChildWithMargins();
// measureChild(child,widthMeasureSpec,heightMeasureSpec);
measureChildren(widthMeasureSpec,heightMeasureSpec);
/**
* 得到父view的size和mode
*/
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
/**
* 在測量大小時,需要計算padding值,而margin值的計算是放在具體的測量中,getTotalWidth,getMaxHeight
*/
int horPadding = getPaddingLeft() + getPaddingRight();
int virPadding = getPaddingBottom() + getPaddingTop();
setMeasuredDimension(widthMode == MeasureSpec.AT_MOST ? getTotalWidth()+horPadding: widthSize+horPadding,
heightMode == MeasureSpec.AT_MOST ? getMaxHeight()+virPadding : heightSize+virPadding);
}
/**
* 在計算總的寬度時,需要將子view的margin值計算進去
* @return
*/
private int getTotalWidth(){
int totalWidth =0;
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
int leftMargin = params.leftMargin;
int rightMargin = params.rightMargin;
int measuredWidth = view.getMeasuredWidth();
totalWidth +=(measuredWidth + leftMargin + rightMargin);
}
return totalWidth;
}
/**
* 計算高度時,也要將子view的margin值計算進去
* @return
*/
private int getMaxHeight(){
int maxHeight =0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
int topMargin = params.topMargin;
int bottomMargin = params.bottomMargin;
int actHeight = topMargin + bottomMargin +child.getMeasuredWidth();
if (actHeight > maxHeight){
maxHeight = actHeight;
}
}
return maxHeight;
}
/**
*在擺放view的過程中,主要計算view防止的l,t,r,b
* margin和padding值其實都是空的,不屬于view
*
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left = getPaddingLeft(); //父view的padding值,空隙
int right =0;
int top = getPaddingTop();
int bottom = getPaddingBottom();
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
int height = child.getMeasuredHeight();
int width = child.getMeasuredWidth();
MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
//子view的margin值
int leftMargin = params.leftMargin;
int rightMargin = params.rightMargin;
int topMargin = params.topMargin;
int bottomMargin = params.bottomMargin;
//擺放的時候要將padding和margin加在一起的空隙都算出來,將view放在實際的位置即可
child.layout(left+leftMargin,top+topMargin,left+leftMargin+width,top+topMargin+height);
left +=(leftMargin+width+rightMargin);
}
}
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
@Override
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(),attrs);
}
public static class LayoutParams extends MarginLayoutParams{
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
public LayoutParams(ViewGroup.LayoutParams p) {
super(p);
}
}
}
總結(jié)
measure: view(這里指的是view類)自身已經(jīng)實現(xiàn)了measure方法,并且也有默認的onMeasure方法,所以我們在自定義view(這里不包括自定義viewgroup)的時候,可以重寫onMeasure方法。
而viewGroup類是抽象類,其并沒有實現(xiàn)view類的measure方法,因此自定義viewGroup是直接使用view類的measure,其中的onMeasure方法需要我們自己去重寫,因為默認的onMeasure方法只是測量了自身的寬高并沒有去測量子viewlayout: 首先要明白layout方法能夠?qū)崿F(xiàn)將自身放置在正確的位置(已經(jīng)實現(xiàn)),而onlayout方法是將每個子view放置在正確的位置,在view類自身已經(jīng)實現(xiàn)了layout方法,只要傳入對應的參數(shù)就可以將自身放在對應的位置上,而在抽象類viewGroup中,將onLayout設置為抽象方法,所以在實現(xiàn)自定義viewGroup的時候就必須要實現(xiàn)對應的onlayout方法,將每個子view放置在對應的位置上(其實就是將子view的layout方法中傳入對應的參數(shù)去實現(xiàn))