android LayoutParams和MarginLayoutParams
LayoutParams
相信大家或多或少都使用过LayoutParams,作为加载layout布局的主力,不论是在xml文件中使用layout进行布局,或者是在 代码中通过LayoutParams.setParams进行布局,都是子控件告诉父控件自己应该如何摆放的一种方式。
在自定义view中,View的测量宽高是由父控件的MeasureSpec和View自身的LayoutParams共同决定的,LayoutParams里面存放着他的具体大小属性,例如Android:layout_width = “match_parent都是LayoutParams的一种应用。
每一个view都有自己的特定的属性,例如background,color,但是这些都是它自己特有的,而LayoutParams是明确当前view在父类控件中如何摆放的,从而确定当前的位置。
MarginLayoutParams
- 当我们设置了layout时候,是不是感觉还缺少了点什么,仅仅只是确定了他的大小,要是我想要测定他的位置怎么弄,就要用到MarginLayoutParams ,通过startMargin方法,确定他的间隔大小,就可以进行一个完整的布局操作。
public MarginLayoutParams(Context c, AttributeSet attrs) {
super();
TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_MarginLayout);
setBaseAttributes(a,
R.styleable.ViewGroup_MarginLayout_layout_width,
R.styleable.ViewGroup_MarginLayout_layout_height);
int margin = a.getDimensionPixelSize(
com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_margin, -1);
if (margin >= 0) {
leftMargin = margin;
topMargin = margin;
rightMargin= margin;
bottomMargin = margin;
} else {
leftMargin = a.getDimensionPixelSize(
R.styleable.ViewGroup_MarginLayout_layout_marginLeft,
UNDEFINED_MARGIN);
if (leftMargin == UNDEFINED_MARGIN) {
mMarginFlags |= LEFT_MARGIN_UNDEFINED_MASK;
leftMargin = DEFAULT_MARGIN_RESOLVED;
}
...
}
...
}
从上面的源码可以看出,该函数将通过传入的属性值,首先获取到layoutMargin,如果该值不存在,才会挨个获取layoutLeftMargin等值。
当完成上面的步骤,就可以通过addView将view添加进去,通过翻看addView的源码可以看到不论是何种方式进入最终都会调用如下的方法
public void addView(View child, int index) {
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
}
- 首先会判定LayoutParams 是否存在,如果不存在则会调用generateDefaultLayoutParams()方法创建一个对应的LayoutParams来达到完成布局的作用。
@Override
protected LayoutParams generateDefaultLayoutParams() {
if (mOrientation == HORIZONTAL) {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
} else if (mOrientation == VERTICAL) {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
return null;
}
可以看到LinerLayout 中的 generateDefaultLayoutParams方法很简单,对产生的LayoutParams进行了修改,如果是横向的,则都设置为WRAP_CONTENT,如果是竖直的则将宽度设置为MATCH_PARENT。
- 通过重写相应viewGroup的LayoutParams方法可以对自定义的viewGroup进行相应的布局补充,达到自己的效果