流式 布局
package com.junyun.tinystore.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import com.junyun.tinystore.R;
/**
* Created by cchao on 2016/7/1.
* E-mail: cchao1024@163.com
* Description: 流式 布局
*/
public class FlowLayout extends ViewGroup {
private static final int DEFAULT_HORIZONTAL_SPACING = 5;
private static final int DEFAULT_VERTICAL_SPACING = 5;
private int mVerticalSpacing;
private int mHorizontalSpacing;
public FlowLayout ( Context context ) {
super ( context );
}
public FlowLayout ( Context context, AttributeSet attrs ) {
super ( context, attrs );
TypedArray a = context.obtainStyledAttributes ( attrs, R.styleable.FlowLayout );
try {
mHorizontalSpacing = a.getDimensionPixelSize (
R.styleable.FlowLayout_horizontal_spacing, DEFAULT_HORIZONTAL_SPACING );
mVerticalSpacing = a.getDimensionPixelSize (
R.styleable.FlowLayout_vertical_spacing, DEFAULT_VERTICAL_SPACING );
} finally {
a.recycle ( );
}
}
public void setHorizontalSpacing ( int pixelSize ) {
mHorizontalSpacing = pixelSize;
}
public void setVerticalSpacing ( int pixelSize ) {
mVerticalSpacing = pixelSize;
}
@Override
protected void onMeasure ( int widthMeasureSpec, int heightMeasureSpec ) {
int myWidth = resolveSize ( 0, widthMeasureSpec );
int paddingLeft = getPaddingLeft ( );
int paddingTop = getPaddingTop ( );
int paddingRight = getPaddingRight ( );
int paddingBottom = getPaddingBottom ( );
int childLeft = paddingLeft;
int childTop = paddingTop;
int lineHeight = 0;
// Measure each child and put the child to the right of previous child
// if there's enough room for it, otherwise, wrap the line and put the child to next line.
for ( int i = 0, childCount = getChildCount ( ) ; i < childCount ; ++ i ) {
View child = getChildAt ( i );
if ( child.getVisibility ( ) != View.GONE ) {
measureChild ( child, widthMeasureSpec, heightMeasureSpec );
} else {
continue;
}
int childWidth = child.getMeasuredWidth ( );
int childHeight = child.getMeasuredHeight ( );
lineHeight = Math.max ( childHeight, lineHeight );
if ( childLeft + childWidth + paddingRight > myWidth ) {
childLeft = paddingLeft;
childTop += mVerticalSpacing + lineHeight;
lineHeight = childHeight;
} else {
childLeft += childWidth + mHorizontalSpacing;
}
}
int wantedHeight = childTop + lineHeight + paddingBottom;
setMeasuredDimension ( myWidth, resolveSize ( wantedHeight, heightMeasureSpec ) );
}
@Override
protected void onLayout ( boolean changed, int l, int t, int r, int b ) {
int myWidth = r - l;
int paddingLeft = getPaddingLeft ( );
int paddingTop = getPaddingTop ( );
int paddingRight = getPaddingRight ( );
int childLeft = paddingLeft;
int childTop = paddingTop;
int lineHeight = 0;
for ( int i = 0, childCount = getChildCount ( ) ; i < childCount ; ++ i ) {
View childView = getChildAt ( i );
if ( childView.getVisibility ( ) == View.GONE ) {
continue;
}
int childWidth = childView.getMeasuredWidth ( );
int childHeight = childView.getMeasuredHeight ( );
lineHeight = Math.max ( childHeight, lineHeight );
if ( childLeft + childWidth + paddingRight > myWidth ) {
childLeft = paddingLeft;
childTop += mVerticalSpacing + lineHeight;
lineHeight = childHeight;
}
childView.layout ( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
childLeft += childWidth + mHorizontalSpacing;
}
}
}
/*
<com.junyun.tinystore.widget.FlowLayout
android:id ="@+id/flow_layout"
android:layout_width ="match_parent"
android:layout_height ="wrap_content"
android:numColumns ="auto_fit"
flowlayout:horizontal_spacing ="24dp"
flowlayout:vertical_spacing ="20dp"/>
*/