Android实战

RecycerView实现Item布局不规则时自动换行

2017-08-15  本文已影响340人  Kokonuts

最近项目上需要实现一个搜索历史的一个布局,由于每次的搜索内容文本长度完全不同,因此布局的时候不可能采用Linear或Grid布局,需要自定义一种布局

RrecycleView的布局都是代理给RecyclerView.LayoutManager去处理的,因此自定义的布局管理器继承自此类,然后重写onLayoutChildren方法去计算布局,详细代码如下

package com.demo;

import android.support.v7.widget.RecyclerView;
import android.view.View;

public class AutoLineFeedLayoutManager extends RecyclerView.LayoutManager {

    public AutoLineFeedLayoutManager() {
        setAutoMeasureEnabled(true);//layoutmanager必须调用此方法设为true才能在onMesure时自动布局
    }

    @Override
    public RecyclerView.LayoutParams generateDefaultLayoutParams() {
        return new RecyclerView.LayoutParams(
                RecyclerView.LayoutParams.WRAP_CONTENT,
                RecyclerView.LayoutParams.WRAP_CONTENT);
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        detachAndScrapAttachedViews(recycler);

        int curLineWidth = 0, curLineTop = 0;//curLineWidth 累加item布局时的x轴偏移curLineTop 累加item布局时的x轴偏移
        int lastLineMaxHeight = 0;
        for (int i = 0; i < getItemCount(); i++) {
            View view = recycler.getViewForPosition(i);
            //获取每个item的布局参数,计算每个item的占用位置时需要加上margin
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();

            addView(view);
            measureChildWithMargins(view, 0, 0);
            int width = getDecoratedMeasuredWidth(view) + params.leftMargin + params.rightMargin;
            int height = getDecoratedMeasuredHeight(view) + params.topMargin + params.bottomMargin;

            curLineWidth += width;//累加当前行已有item的宽度
            if (curLineWidth <= getWidth()) {//如果累加的宽度小于等于RecyclerView的宽度,不需要换行
                layoutDecorated(view, curLineWidth - width + params.leftMargin, curLineTop + params.topMargin, curLineWidth - params.rightMargin, curLineTop + height - params.bottomMargin);//布局item的真实位置
                //比较当前行多有item的最大高度,用于换行后计算item在y轴上的偏移量
                lastLineMaxHeight = Math.max(lastLineMaxHeight, height);
            } else {//换行
                curLineWidth = width;
                if (lastLineMaxHeight == 0) {
                    lastLineMaxHeight = height;
                }
                //记录当前行top
                curLineTop += lastLineMaxHeight;

                layoutDecorated(view, params.leftMargin, curLineTop + params.topMargin, width - params.rightMargin, curLineTop + height - params.bottomMargin);
                lastLineMaxHeight = height;
            }
        }
    }
}

写好LayoutManager之后使用时只需要new一个此Manager然后设置给RecyclerView即可,如下

RecyclerView recycler = (RecyclerView)findViewById(R.id.recycler);
recycler.setLayoutManager(new AutoLineFeedLayoutManager());

如上代码设置后,item布局时会尽量布局在一行,当此行显示不下时自动换行,效果如下图

图片.png
上一篇 下一篇

猜你喜欢

热点阅读