AutoLayoutActivity
AutoLayoutActivity
public class AutoLayoutActivity extends FragmentActivity {
private static final String LAYOUT_LINEARLAYOUT = "LinearLayout";
private static final String LAYOUT_FRAMELAYOUT = "FrameLayout";
private static final String LAYOUT_RELATIVELAYOUT = "RelativeLayout";
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
View view = null;
if (name.equals(LAYOUT_FRAMELAYOUT)) {
view = new AutoFrameLayout(context, attrs);
}
if (name.equals(LAYOUT_LINEARLAYOUT)) {
view = new AutoLinearLayout(context, attrs);
}
if (name.equals(LAYOUT_RELATIVELAYOUT)) {
view = new AutoRelativeLayout(context, attrs);
}
if (view != null) return view;
return super.onCreateView(name, context, attrs);
}
}
我們可以發現,只是做了name的判斷,
如果是屬性中的3中Layout, 會自動替換成 對應的AutoXXXLayout
如果不是,直接調用父類的 View onCreateView(String name, Context context, AttributeSet attrs) 即可
LinearLayout -> AutoLinearLayout
RelativeLayout -> AutoRelativeLayout
FrameLayout -> AutoFrameLayout
AutoLinearLayout
我們來看一看對應的源碼
public class AutoLinearLayout extends LinearLayout {
private AutoLayoutHelper mHelper = new AutoLayoutHelper(this);
public AutoLinearLayout(Context context) {
super(context);
}
public AutoLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public AutoLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public AutoLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!isInEditMode())
mHelper.adjustChildren();
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new AutoLinearLayout.LayoutParams(getContext(), attrs);
}
public static class LayoutParams extends LinearLayout.LayoutParams
implements AutoLayoutHelper.AutoLayoutParams {
private AutoLayoutInfo mAutoLayoutInfo;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
mAutoLayoutInfo = AutoLayoutHelper.getAutoLayoutInfo(c, attrs);
}
@Override
public AutoLayoutInfo getAutoLayoutInfo() {
return mAutoLayoutInfo;
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
public LayoutParams(MarginLayoutParams source) {
super(source);
}
}
}
我們可以發現,類中只關聯了一個 AutoLayoutHelper類
重寫onMeasure方法
這里同樣會調用關聯AutoLayoutHelper的對象
這里,在調用 父類
super.onMeasure(widthMeasureSpec, heightMeasureSpec)之前
會去調用 關聯AutoLayoutHelper的 mHelper.adjustChildren();
這里有 isInEditMode() 判斷
是為了判斷 是否在例如 可視化編輯器 中打開
這樣可以避免不必要的報錯
可以參考:
http://blog.csdn.net/lamp_zy/article/details/9405925
重寫generateLayoutParams方法
我們先來看一下, 父類 LinearLayout中, generateLayoutParams方法的實現
父類 LinearLayout中, generateLayoutParams方法的實現為:
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LinearLayout.LayoutParams(getContext(), attrs);
}
再看一下這個return new 的 LinearLayout.LayoutParams 靜態內部類
(自己理解靜態內部類,一般內部類 就是和本來關系比較密切,在其他地方不需要調用,非靜態內部類可以調用外部類的屬性和方法, 比較方便。 靜態內部類相對于非靜態內部類,獨立性較強)
public static class LayoutParams extends ViewGroup.MarginLayoutParams {
/**
* Indicates how much of the extra space in the LinearLayout will be
* allocated to the view associated with these LayoutParams. Specify
* 0 if the view should not be stretched. Otherwise the extra pixels
* will be pro-rated among all views whose weight is greater than 0.
*/
@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;
}
/**
* Creates a new set of layout parameters with the specified width, height
* and weight.
*
* @param width the width, either {@link #MATCH_PARENT},
* {@link #WRAP_CONTENT} or a fixed size in pixels
* @param height the height, either {@link #MATCH_PARENT},
* {@link #WRAP_CONTENT} or a fixed size in pixels
* @param weight the weight
*/
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);
}
/**
* Copy constructor. Clones the width, height, margin values, weight,
* and gravity of the source.
*
* @param source The layout params to copy from.
*/
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 + "}";
}
/** @hide */
@Override
protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) {
super.encodeProperties(encoder);
encoder.addProperty("layout:weight", weight);
encoder.addProperty("layout:gravity", gravity);
}
}
LinearLayout.LayoutParams類中,注解較多,并且是不常用的注解
再加上也是 繼承 ViewGroup.MarginLayoutParams 對應的內部靜態類
自己也不花時間研究,不和大家扯淡了
讓我們回到 鴻洋大神 的 AutoLinearLayout的
靜態內部類AutoLinearLayout.LayoutParams
public static class LayoutParams extends LinearLayout.LayoutParams
implements AutoLayoutHelper.AutoLayoutParams
{
private AutoLayoutInfo mAutoLayoutInfo;
public LayoutParams(Context c, AttributeSet attrs)
{
super(c, attrs);
mAutoLayoutInfo = AutoLayoutHelper.getAutoLayoutInfo(c, attrs);
}
@Override
public AutoLayoutInfo getAutoLayoutInfo()
{
return mAutoLayoutInfo;
}
public LayoutParams(int width, int height)
{
super(width, height);
}
public LayoutParams(ViewGroup.LayoutParams source)
{
super(source);
}
public LayoutParams(MarginLayoutParams source)
{
super(source);
}
}
這里我們發現, 這個類除了上面說到的 extends LinearLayout.LayoutParams,
還 implements AutoLayoutHelper.AutoLayoutParams。
而對應的實現, 也只是在LayoutParams(Context c, AttributeSet attrs)構造中
給 屬性private AutoLayoutInfo mAutoLayoutInfo;
傳遞了一下AutoLayoutHelper的實現
再通過接口實現,返回對象
可以發現,繞了一圈, 最后只是把具體的實現傳遞給父類的邏輯中
(自己對這些Override的方法也不太熟悉, 為什么要Override這幾個方法,而不從別的方法下手,自己以后再做考慮)
后面我們再說明下,是怎么通過AutoLayoutHelper把 傳遞值 和 計算 聯系起來的
AutoRelativeLayout 和 AutoFrameLayout
這里AutoRelativeLayout 和 AutoFrameLayout都類似,
都只是通過 關聯和依賴 AutoLayoutHelper ,
Override對應的
onMeasure(int widthMeasureSpec, int heightMeasureSpec) 和 generateLayoutParams(AttributeSet attrs)
通過靜態內部類 的接口, 傳遞 AutoLayoutHelper的實現
返回 AutoLayoutInfo 對象
AutoLayoutInfo類
我們看看 AutoLayoutInfo 類
public class AutoLayoutInfo {
private List<AutoAttr> autoAttrs = new ArrayList<>();
public void addAttr(AutoAttr autoAttr) {
autoAttrs.add(autoAttr);
}
public void fillAttrs(View view) {
for (AutoAttr autoAttr : autoAttrs) {
autoAttr.apply(view);
}
}
@Override
public String toString() {
return "AutoLayoutInfo{" +
"autoAttrs=" + autoAttrs +
'}';
}
}
我們可以發現,其實也只是一個簡單的容器類
通過 addAttr(AutoAttr autoAttr) 給ArrayList容器add添加對象
通過 fillAttrs(View view) 去讓容器中AutoAttr和依賴的view關系
后續
具體類之間的關系,我們后面再慢慢分析
下一篇我們可以了解鴻洋AutoLayout代碼分析(四):剩下的類