1 ViewGroup类中包含两个静态内部类:LayoutParams 和MarginLayoutParams
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
...省略
public static class LayoutParams {
...省略
}
public static class MarginLayoutParams extends ViewGroup.LayoutParams {
...省略
}
...省略
}
这两个布局属性是提供给被它所包含的子View使用的。如
layout_width,layout_height等等。自定义ViewGroup如果要提供自定义的布局需要继承MarginLayoutParams 来重写其中的布局方法,比如LinearLayout ,如下
<LinearLayout
android:layout_width="150dp"
android:layout_height="150dp" >
<!-- 使用自定义view -->
<com.stone.view.CustomView1
android:layout_width="wrap_content"
android:layout_height="fill_parent"
custom:score="60%"
custom:rotation="-45"
custom:color="#3f00ff00" />
</LinearLayout>
上述自定义View中的布局参数(6,7两行)是包裹他的布局所定义的,如果自定义View被一个自定义的ViewGroup包裹,那么ViewGroup需要定义自己的布局参数。
LinearLayout的布局类源码如下:
public static class LayoutParams extends ViewGroup.MarginLayoutParams {
@ViewDebug.ExportedProperty(category = "layout")
public float weight;
/**
* Gravity for the view associated with these LayoutParams.
*
* @see android.view.Gravity
*/
@ViewDebug.ExportedProperty(category = "layout", mapping = {
@ViewDebug.IntToString(from = -1, to = "NONE"),
@ViewDebug.IntToString(from = Gravity.NO_GRAVITY, to = "NONE"),
@ViewDebug.IntToString(from = Gravity.TOP, to = "TOP"),
@ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"),
@ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"),
@ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"),
@ViewDebug.IntToString(from = Gravity.START, to = "START"),
@ViewDebug.IntToString(from = Gravity.END, to = "END"),
@ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"),
@ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"),
@ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
@ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL, to = "FILL_HORIZONTAL"),
@ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"),
@ViewDebug.IntToString(from = Gravity.FILL, to = "FILL")
})
public int gravity = -1;
/**
* {@inheritDoc}
*/
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
TypedArray a =
c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.LinearLayout_Layout);
weight = a.getFloat(com.android.internal.R.styleable.LinearLayout_Layout_layout_weight, 0);
gravity = a.getInt(com.android.internal.R.styleable.LinearLayout_Layout_layout_gravity, -1);
a.recycle();
}
/**
* {@inheritDoc}
*/
public LayoutParams(int width, int height) {
super(width, height);
weight = 0;
}
public LayoutParams(int width, int height, float weight) {
super(width, height);
this.weight = weight;
}
/**
* {@inheritDoc}
*/
public LayoutParams(ViewGroup.LayoutParams p) {
super(p);
}
/**
* {@inheritDoc}
*/
public LayoutParams(ViewGroup.MarginLayoutParams source) {
super(source);
}
public LayoutParams(LayoutParams source) {
super(source);
this.weight = source.weight;
this.gravity = source.gravity;
}
@Override
public String debug(String output) {
return output + "LinearLayout.LayoutParams={width=" + sizeToString(width) +
", height=" + sizeToString(height) + " weight=" + weight + "}";
}
}
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
...
/**
* The layout parameters associated with this view and used by the parent
* {@link android.view.ViewGroup} to determine how this view should be
* laid out.
* {@hide}
*/
//每个View均拥有LayoutParams属性,View添加到ViewGroup时的布局参数
protected ViewGroup.LayoutParams mLayoutParams;
public void setLayoutParams(ViewGroup.LayoutParams params) {
if (params == null) {
throw new NullPointerException("Layout parameters cannot be null");
}
mLayoutParams = params;
resolveLayoutParams();
if (mParent instanceof ViewGroup) {
((ViewGroup) mParent).onSetLayoutParams(this, params);
}
requestLayout();
}
...
}
2 invalidate(),requestLayout()以及requestFocus()均为View类中的方法,这三个方法最终会调用到ViewRoot中的schedulTraversale()方法,该函数然后发起一个异步消息,消息处理中调用performTraverser()方法对整个View进行遍历。
参考Android中View绘制流程以及invalidate()等相关方法分析