<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 给我们的viewgroup定义专属的自己的属性 并且指定类型 -->
<declare-styleable name="custom_view_group">
<attr name="horizontal_spacing" format="dimension" />
<attr name="vertical_spacing" format="dimension" />
</declare-styleable>
</resources><?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="horizontal_spacing">10dp</dimen>
<dimen name="vertical_spacing">10dp</dimen>
</resources>package com.yufeng.androidtest; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; public class CustomViewGroup extends ViewGroup { private int mHorizontalSpacing; private int mVerticalSpacing; private CustomLayoutParams[] point; public CustomViewGroup(Context context, AttributeSet attrs) { super(context, attrs); initCustomViewGroup(context, attrs); } private void initCustomViewGroup(Context context, AttributeSet attrs) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.custom_view_group); // 获取默认的间距并赋值给定制的属性 mHorizontalSpacing = typedArray.getDimensionPixelSize( R.styleable.custom_view_group_horizontal_spacing, getResources() .getDimensionPixelSize(R.dimen.horizontal_spacing)); mVerticalSpacing = typedArray.getDimensionPixelSize( R.styleable.custom_view_group_vertical_spacing, getResources() .getDimensionPixelSize(R.dimen.vertical_spacing)); // 释放 typedArray.recycle(); } public CustomViewGroup(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 存放每个控件的点用自己写的CustomLayoutParams // 用于子控件的x和y轴位置以及本控件的最终大小 int width = 0; int height = 0; // 获取本控件下子控件的个数 final int count = getChildCount(); point = new CustomLayoutParams[count]; for (int i = 0; i < count; i++) { // 获取子控件 View child = getChildAt(i); // 测量子控件的长度让子控件去搞吧,反正系统写好了,如果子控件还有子控件他也会才处理的 measureChild(child, widthMeasureSpec, heightMeasureSpec); // 计算好我们给设定的子控件位置 定制自己的控件 width = getPaddingLeft() + mHorizontalSpacing * i; height = getPaddingTop() + mVerticalSpacing * i; // 保存到子控件的点到CustomLayoutParams中 CustomLayoutParams customLayoutParams = new CustomLayoutParams(); customLayoutParams.x = width; customLayoutParams.y = height; point[i] = customLayoutParams; } width += getPaddingRight() + getChildAt(count - 1).getMeasuredWidth(); height += getPaddingBottom() + getChildAt(count - 1).getMeasuredHeight(); // 必须调用计算自己的大小 setMeasuredDimension(resolveSize(width, widthMeasureSpec), resolveSize(height, heightMeasureSpec)); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // 把他和控件都画出来 final int count = getChildCount(); for (int i = 0; i < count; i++) { // 获取子控件 View view = getChildAt(i); // 画控件,就是从那画到那 view.layout(point[i].x, point[i].y, point[i].x + view.getMeasuredWidth(), point[i].y + view.getMeasuredHeight()); } } class CustomLayoutParams { // 用作保存点 int x; int y; } }
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cascade="http://schemas.android.com/apk/res/com.yufeng.androidtest"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!--xmlns:cascade 使用自定义的属性必须声明引用 只需要把后半部分改成你的包名即可 -->
<com.yufeng.androidtest.CustomViewGroup
android:id="@+id/customViewGroup1"
android:layout_width="match_parent"
android:layout_height="match_parent"
cascade:horizontal_spacing="10dp"
cascade:vertical_spacing="10dp" >
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#FF0000"
/>
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00FF00"
/>
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#0000FF"
/>
</com.yufeng.androidtest.CustomViewGroup>
</LinearLayout>原文:http://blog.csdn.net/u013134391/article/details/26108983