Android开发实践:自定义ViewGroup的onLayout()分析(2)

<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值。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/9192d32d4c2a3c1b98909b6f9592543f.html