查资料
- 改变LayoutParam是什么原理?
LayoutParam的基类是ViewGroup.LayoutParams,只有宽高两个属性
常用的直接子类只有一个 MarginLayoutParams,他也是ViewGroup的静态内部类,多出了margin的属性。
可以看到常用的FrameLayout.LayoutParams, GridLayout.LayoutParams, LinearLayout.LayoutParams, RelativeLayout.LayoutParams,都是他的子类,包括新出的约束布局,也是
所以常见的parent view的LayoutParam都可以强转型为MarginLayoutParams。
onMeasure()方法里,取得的都是每个子view的LayoutParams,来进行测量,那么每个子view的LayoutParam都是在那里被设置的?
答案再ViewGroup的addView方法里
/**
* 重载方法1:添加一个子View
* 如果这个子View还没有LayoutParams,就为子View设置当前ViewGroup默认的LayoutParams
*/
public void addView(View child) {
addView(child, -1);
}
/**
* 重载方法2:在指定位置添加一个子View
* 如果这个子View还没有LayoutParams,就为子View设置当前ViewGroup默认的LayoutParams
* @param index View将在ViewGroup中被添加的位置(-1代表添加到末尾)
*/
public void addView(View child, int index) {
if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();// 生成当前ViewGroup默认的LayoutParams
if (params == null) {
throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
}
/**
* 重载方法3:添加一个子View
* 使用当前ViewGroup默认的LayoutParams,并以传入参数作为LayoutParams的width和height
*/
public void addView(View child, int width, int height) {
final LayoutParams params = generateDefaultLayoutParams(); // 生成当前ViewGroup默认的LayoutParams
params.width = width;
params.height = height;
addView(child, -1, params);
}
/**
* 重载方法4:添加一个子View,并使用传入的LayoutParams
*/
@Override
public void addView(View child, LayoutParams params) {
addView(child, -1, params);
}
/**
* 重载方法4:在指定位置添加一个子View,并使用传入的LayoutParams
*/
public void addView(View child, int index, LayoutParams params) {
if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}
?
mLayoutParams = params;
resolveLayoutParams();
if (mParent instanceof ViewGroup) {
((ViewGroup) mParent).onSetLayoutParams(this, params);
}
requestLayout();
}
可以看到也是重绘了自己,如果有父View,会调用一个父View的方法,这个其实就是也是重绘父View
/** @hide */
protected void onSetLayoutParams(View child, LayoutParams layoutParams) {
requestLayout();
}
也就是调用setLayout会从父View开始重绘。