流布局相信大家应该都比较清楚,几乎每个人都写过。
开源的也是非常多!
就不过多介绍啦,这里做了一个比较简洁且支持Padding以及间隔的流布局供大家参考。
代码比较简单粗暴就不过多介绍,按照惯例上代码:
<declare-styleable name="flowLayout">
<attr name="VerticalSpacer" format="integer" />
<attr name="HorizontalSpacer" format="integer" />
</declare-styleable>
/** * Created by Liqingwen on 7/13/16.
* Email: Liqingqingqingwen@163.com
*/
public class FlowLayout extends ViewGroup {
/**水平间距*/
public final static int DEFAULT_HORIZONTAL_SPACER = 5;
/**垂直间距*/
public final static int DEFAULT_VERTICAL_SPACER = 5;
private int mHorizontalSpacer;
private int mVerticalSpacer;
public FlowLayout(Context context) {
super(context);
}
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.flowLayout); try {
mHorizontalSpacer = array.getInteger(R.styleable.flowLayout_HorizontalSpacer,DEFAULT_HORIZONTAL_SPACER);
mVerticalSpacer = array.getInteger(R.styleable.flowLayout_VerticalSpacer,DEFAULT_VERTICAL_SPACER);
}finally {
array.recycle();
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int mFlowLayoutWidth = getMeasuredWidth();
int mFlowLayoutPaddingLeft = getPaddingLeft();
int mFlowLayoutPaddingRight = getPaddingRight();
int mFlowLayoutPaddingBottom = getPaddingBottom();
int mFlowLayoutPaddingTop = getPaddingTop();
int mChildTotalWidth = mFlowLayoutPaddingLeft;
int mChildTotalHeight = mFlowLayoutPaddingTop ;
int mChildCount = getChildCount();
for (int i = 0; i < mChildCount ;i ++) {
View mChildView = getChildAt(i);
if (mChildView.getVisibility() == View.GONE)
continue;
int mChildViewMeasuredHeight = mChildView.getMeasuredHeight();
int mChildViewMeasuredWidth = mChildView.getMeasuredWidth();
if(mChildTotalWidth + mChildViewMeasuredWidth > mFlowLayoutWidth - mFlowLayoutPaddingLeft - mFlowLayoutPaddingRight){
mChildTotalWidth = mFlowLayoutPaddingLeft;
mChildTotalHeight += mVerticalSpacer +
mChildViewMeasuredHeight ;
}
setChildFrame(mChildView,mChildTotalWidth,mChildTotalHeight,mChildTotalWidth + mChildViewMeasuredWidth, mChildTotalHeight + mChildViewMeasuredHeight);
mChildTotalWidth += mHorizontalSpacer + mChildViewMeasuredWidth;
}
}
private void setChildFrame(@NonNull View mView, int l, int t, int r, int b){
mView.layout(l,t,r,b);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int mFlowLayoutWidth = resolveSize(0,widthMeasureSpec);
int mFlowLayoutPaddingLeft = getPaddingLeft();
int mFlowLayoutPaddingRight = getPaddingRight();
int mFlowLayoutPaddingBottom = getPaddingBottom();
int mFlowLayoutPaddingTop = getPaddingTop();
int mChildTotalWidth = mFlowLayoutPaddingLeft ;
int mTotalLineHeight = 0;
int mChildCount = getChildCount();
for (int i = 0; i < mChildCount ;i ++){
View mChildView = getChildAt(i);
if(mChildView.getVisibility() == View.GONE)
continue;
measureChild(mChildView,widthMeasureSpec,heightMeasureSpec);
int mChildViewMeasuredHeight = mChildView.getMeasuredHeight();
int mChildViewMeasuredWidth = mChildView.getMeasuredWidth();
MarginLayoutParams mMarginLayoutParams = (MarginLayoutParams) mChildView.getLayoutParams();
mTotalLineHeight = Math.max(mTotalLineHeight,mChildViewMeasuredHeight);
if(mChildTotalWidth +mChildViewMeasuredWidth > mFlowLayoutWidth - mFlowLayoutPaddingLeft - mFlowLayoutPaddingRight){
mChildTotalWidth = mFlowLayoutPaddingLeft; mTotalLineHeight += mVerticalSpacer + mChildViewMeasuredHeight ;
}else{
mChildTotalWidth += mHorizontalSpacer + mChildViewMeasuredWidth ;
}
setMeasuredDimension(mFlowLayoutWidth,resolveSize(mFlowLayoutPaddingTop + mTotalLineHeight + mFlowLayoutPaddingBottom,heightMeasureSpec));
}
}
/**
*与当前ViewGroup对应的LayoutParams
* 这里想要支持Margin就必须实现generateLayoutParams 方法
* 否则会强制转换异常!
* 目前LayoutFlow不支持Margin 等有好点思路再加上
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
*/
}
整体效果如下:
flow.jpeg
当然啦!这个布局也有点小 bug 图片如下:
bug.jpeg
这个bug呢我就不解决啦!
最近忙着做一个 模仿windowsPhone 主页的磁贴布局,嗯…这个bug有点像windowsPhone 主页的磁贴…..
解决的方式也比较简单只要获取上一行 判断谁的高最大ok啦!
但是流布局的字 View一般都是被当成热词使用高度都是一样的,所以这个也不算bug,不过要是你的子View款高度不确定的话那就另当别论。
下一篇 : 模仿windowsPhone 主页的磁贴