android 自动换行的流式布局

本文介绍了一种自定义的FlowGroup布局实现方案,通过重写onMeasure和onLayout方法,使得子视图能够自动换行排列。适用于Android应用中需要灵活布局的场景。

自定义FlowGroup继承ViewGroup,通过实现onMeasure和onLayout方法,实现子控件的自动换行

package com.shilian.yibo.view;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/**
 * 流式布局的viewgroup
 * Created by Burn on 2017/4/24.
 */
public class FlowGroup extends ViewGroup {

    /**
     * 构造方法
     * */
    public FlowGroup(Context context) {
        super(context);
    }

    public FlowGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FlowGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public FlowGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    /**
     * 重写onMeasure方法,计算viewgroup的尺寸,保存子控件数据
     * */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取FlowGroup的模式和尺寸
        int sizeWidth=MeasureSpec.getSize(widthMeasureSpec);
        int sizeHeight=MeasureSpec.getSize(heightMeasureSpec);
        int modeWidth=MeasureSpec.getMode(widthMeasureSpec);
        int modeHeight=MeasureSpec.getMode(heightMeasureSpec);

        int width=0;//总宽
        int height=0;//总高
        int lineWidth=0;//行宽
        int lineHeight=0;//行高

        //遍历子控件获取数据
        int mCount=getChildCount();
        for (int i=0;i<mCount;i++){
            View child=getChildAt(i);
            measureChild(child,widthMeasureSpec,heightMeasureSpec);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            int childWidth=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
            int childHeight=child.getMeasuredHeight()+lp.topMargin+lp.bottomMargin;
            if (lineWidth+childWidth<=sizeWidth){
                lineWidth+=childWidth;
                lineHeight=Math.max(lineHeight,childHeight);
            }else {
                width=Math.max(width,lineWidth);
                height+=lineHeight;
                lineWidth=childWidth;
                lineHeight=childHeight;
            }
            if (i==mCount-1){
                width=Math.max(width,lineWidth);
                height+=lineHeight;
            }
        }
        setMeasuredDimension(((modeWidth==MeasureSpec.EXACTLY)?sizeWidth:width),((modeHeight==MeasureSpec.EXACTLY)?sizeHeight:height));
    }

    private List<List<View>> mAllViews = new ArrayList<List<View>>();
    /**
     * 记录每一行的最大高度
     */
    private List<Integer> mLineHeight = new ArrayList<Integer>();

    /**
     * 重写onLayout方法,实现子控件布局
     * */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left=0;//控件左侧位置
        int top=0;//控件上方位置

        int lineWidth=0;//行宽
        int lineHeight=0;//行高

        int mCount=getChildCount();
        for (int i=0;i<mCount;i++){
            View child=getChildAt(i);
            MarginLayoutParams lp= (MarginLayoutParams) child.getLayoutParams();

            if (child.getVisibility()==View.GONE){
                continue;
            }

            int childWidth=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
            int childHeight=child.getMeasuredHeight()+lp.topMargin+lp.bottomMargin;
            if (lineWidth+childWidth<=getWidth()){
                lineWidth+=childWidth;
                lineHeight=Math.max(lineHeight,childHeight);
            }else {
                left=0;
                top+=lineHeight;
                lineWidth=childWidth;
                lineHeight=childHeight;
            }
            int lc=left+lp.leftMargin;
            int tc=top+lp.topMargin;
            int rc=lc+child.getMeasuredWidth();
            int bc=tc+child.getMeasuredHeight();
            child.layout(lc, tc, rc, bc);
            left+=childWidth;
        }
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(),attrs);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值