自定义ViewGroup的的讲解有很多,没必要再过多的赘述,网上一搜一大把,下面写一个简单的例子,供自己以后复习的时候可以用到。
- 自定义属性
在values下面新建一个attrs.xml文件,用来自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CascadeLayout">
<attr name="horizontal_spacing" format="dimension"/>
<attr name="veritcal_spacing" format="dimension"/>
</declare-styleable>
</resources>
- 新建两个属性的默认的尺寸大小在dimens.xml文件中
<dimen name="default_horizontal_spacing">15dp</dimen>
<dimen name="default_vertical_spacing">15dp</dimen>
- 构建我们的主体类CascadeLayout
package com.gearmotion.app.cascadeviewgroupmotion;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by Charles on 2016/3/22.
*/
public class CascadeLayout extends ViewGroup {
//水平间距
private int mHorizontalSpacing;
//垂直间距
private int mVerticalSpacing;
public CascadeLayout(Context context) {
this(context, null);
}
public CascadeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CascadeLayout);
mHorizontalSpacing = a.getDimensionPixelSize(R.styleable.CascadeLayout_horizontal_spacing,
this.getResources().getDimensionPixelSize(R.dimen.default_horizontal_spacing));
mVerticalSpacing = a.getDimensionPixelSize(R.styleable.CascadeLayout_veritcal_spacing, this
.getResources().getDimensionPixelSize(R.dimen.default_vertical_spacing));
a.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int count = this.getChildCount();
int width = 0;
int height = 0;
for (int i = 0; i < count; i++) {
View currentView = this.getChildAt(i);
//对每个子view测量
measureChild(currentView, widthMeasureSpec, heightMeasureSpec);
LayoutParams lp = (LayoutParams) currentView.getLayoutParams();
width = getPaddingLeft() + mHorizontalSpacing * i;
height = getPaddingTop() + mVerticalSpacing * i;
//设置每个子view的坐标信息
lp.x = width;
lp.y = height;
}
width += getChildAt(count - 1).getMeasuredWidth();
height += 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 = this.getChildCount();
for (int i = 0; i < count; i++) {
View view = this.getChildAt(i);
LayoutParams lp = (LayoutParams) view.getLayoutParams();
view.layout(lp.x, lp.y, lp.x + view.getMeasuredWidth(), lp.y + view.getMeasuredHeight());
}
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams
.WRAP_CONTENT);
}
@Override
protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
//创建自定义LayoutParams用来记录位置信息
private static class LayoutParams extends ViewGroup.LayoutParams {
//用来保存坐标信息
public int x;
public int y;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
public LayoutParams(int width, int height) {
super(width, height);
}
}
}
- xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<com.gearmotion.app.cascadeviewgroupmotion.CascadeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ns="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
ns:horizontal_spacing="20dp"
ns:veritcal_spacing="20dp"
tools:context="com.gearmotion.app.cascadeviewgroupmotion.MainActivity">
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#668B8B"/>
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#00FF00"/>
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#FF6A6A"/>
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#9BCD9B"/>
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#000080"/>
</com.gearmotion.app.cascadeviewgroupmotion.CascadeLayout>
- 最后显示的效果如下: