<com.titcktick.customview.CustomViewGroup xmlns:android=""
xmlns:tools=""
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="10dp"
android:background="@android:color/black"/>
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="10dp"
android:background="@android:color/black"/>
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="10dp"
android:background="@android:color/black"/>
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="10dp"
android:background="@android:color/black"/>
</com.titcktick.customview.CustomViewGroup>
5. 添加layout_margin
为了让核心逻辑更加清晰,上面的onLayout()实现我隐去了margin的计算,这样就会导致子控件的layout_margin不起效果,所以上述效果是子控件一个个紧挨着排列,中间没有空隙。那么,下面我们来研究下如何添加margin效果。
其实,如果要自定义ViewGroup支持子控件的layout_margin参数,则自定义的ViewGroup类必须重载generateLayoutParams()函数,并且在该函数中返回一个ViewGroup.MarginLayoutParams派生类对象,这样才能使用margin参数。
ViewGroup.MarginLayoutParams的定义关键部分如下,它记录了子控件的layout_margin值:
public static class MarginLayoutParams extends ViewGroup.LayoutParams {
public int leftMargin;
public int topMargin;
public int rightMargin;
public int bottomMargin;
}
你可以跟踪源码看看,其实XML文件中View的layout_xxx参数都是被传递到了各种自定义ViewGroup.LayoutParams派生类对象中。例如LinearLayout的LayoutParams定义的关键部分如下:
public class LinearLayout extends ViewGroup {
public static class LayoutParams extends ViewGroup.MarginLayoutParams {
public float weight;
public int gravity = -1;
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();
}
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LinearLayout.LayoutParams(getContext(), attrs);
}
}
这样你大概就可以理解为什么LinearLayout的子控件支持weight和gravity的设置了吧,当然我们也可以这样自定义一些属于我们ViewGroup特有的params,这里就不详细讨论了,我们只继承MarginLayoutParams来获取子控件的margin值。