与GridLayoutManager试图解决WRAP_CONTENT RecyclerView [英] RecyclerView with GridLayoutManager trying to solve wrap_content

查看:2507
本文介绍了与GridLayoutManager试图解决WRAP_CONTENT RecyclerView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试解决以下内容:


  • 使用RecyclerView

  • 与GridLayoutManager

  • 以固定细胞宽度

  • recyclerview只调整到必要的高度(WRAP_CONTENT)

我尝试使用以下code,但问题是,它不工作,我还没有找到任何工作的例子不说也罢正确重绘时方向的变化。

 公共类AutofitRecyclerView扩展RecyclerView {
    私人MyGridLayoutManager经理;
    私人INT columnWidth时= -1;    公共AutofitRecyclerView(上下文的背景下){
        超级(上下文);
        的init(背景下,NULL);
    }    公共AutofitRecyclerView(上下文的背景下,ATTRS的AttributeSet){
        超(背景下,ATTRS);
        的init(背景下,ATTRS);
    }    公共AutofitRecyclerView(上下文的背景下,ATTRS的AttributeSet,诠释defStyle){
        超(背景下,ATTRS,defStyle);
        的init(背景下,ATTRS);
    }    私人无效的init(上下文的背景下,ATTRS的AttributeSet){
        如果(ATTRS!= NULL){
            INT [] = attrsArray {
                    android.R.attr.columnWidth
            };
            TypedArray阵列= context.obtainStyledAttributes(ATTRS,attrsArray);
            columnWidth时= array.getDimensionPixelSize(0,-1);
            array.recycle();
        }        经理=新MyGridLayoutManager(的getContext(),1);
        setLayoutManager(经理);
    }    @覆盖
    保护无效onMeasure(INT widthSpec,诠释heightSpec){
        super.onMeasure(widthSpec,heightSpec);
        如果(columnWidth时大于0){            INT MW = getMeasuredWidth();            INT spanCount = Math.max(1兆瓦/ columnWidth时);
            manager.setSpanCount(spanCount);
        }        INT numOfFullRows = manager.getItemCount()/ manager.getSpanCount();        如果(manager.getItemCount()%manager.getSpanCount()大于0)
        {
            numOfFullRows ++;
        }        如果(getChildCount()大于0){
            INT H = 0;
            尝试{
                H = manager.getChildAt(0).getMeasuredHeight();
            }赶上(例外五){
                e.printStackTrace();
            }            如果(H!= 0){
                。getLayoutParams()高度= numOfFullRows * H;
            }
        }
    }
}


解决方案

根据上code公布了连接器,我想出了一个支持不同的行/列大小(虽然我承认没有测试过)以下的解决方案,作为项目的装饰品考虑的大小和正确处理不同的衡量方式。

下面是code:

 进口android.content.Context;
进口android.graphics.Rect;
进口android.support.v7.widget.GridLayoutManager;
进口android.support.v7.widget.RecyclerView;
进口android.view.View;
进口android.view.ViewGroup;公共类WrappableGridLayoutManager扩展GridLayoutManager {    公共WrappableGridLayoutManager(上下文的背景下,诠释spanCount){
        超(背景下,spanCount);
    }    私人诠释[] = measuredSize新INT [2];    @覆盖
    公共无效onMeasure(RecyclerView.Recycler回收,RecyclerView.State状态,INT widthSpec,诠释heightSpec){
        最终诠释widthMode = View.MeasureSpec.getMode(widthSpec);
        最终诠释heightMode = View.MeasureSpec.getMode(heightSpec);
        最终诠释widthSize = View.MeasureSpec.getSize(widthSpec);
        最终诠释heightSize = View.MeasureSpec.getSize(heightSpec);        INT spanWidth = 0;
        INT spanHeight = 0;        INT viewWidth = 0;
        INT viewHeight = 0;        INT spanCount = getSpanCount();        的for(int i = 0; I< getItemCount();我++){            measureScrapChild(回收,我,View.MeasureSpec.makeMeasureSpec(I,View.MeasureSpec.UNSPECIFIED),View.MeasureSpec.makeMeasureSpec(I,View.MeasureSpec.UNSPECIFIED),measuredSize);            如果(I%spanCount == 0){
                spanWidth = measuredSize [0];
                spanHeight = measuredSize [1];
            }其他{
                如果(getOrientation()==垂直){
                    spanWidth + = measuredSize [0];
                    spanHeight = Math.max(spanHeight,measuredSize [1]);
                }其他{
                    spanWidth = Math.max(spanWidth,measuredSize [0]);
                    spanHeight + = measuredSize [1];
                }
            }            如果(ⅰ%spanCount == spanCount - 1 ||我== getItemCount() - 1){
                如果(getOrientation()==垂直){
                    viewWidth = Math.max(viewWidth,spanWidth);
                    viewHeight + = spanHeight;
                }其他{
                    viewWidth + = spanWidth;
                    viewHeight = Math.max(viewHeight,spanHeight);
                }
            }
        }        INT finalWidth;
        INT finalHeight;        开关(widthMode){
            案例View.MeasureSpec.EXACTLY:
                finalWidth = widthSize;
                打破;
            案例View.MeasureSpec.AT_MOST:
                finalWidth = Math.min(widthSize,viewWidth);
                打破;
            案例View.MeasureSpec.UNSPECIFIED:
                finalWidth = viewWidth;
                打破;
            默认:
                finalWidth = widthSize;
                打破;
        }        开关(heightMode){
            案例View.MeasureSpec.EXACTLY:
                finalHeight = heightSize;
                打破;
            案例View.MeasureSpec.AT_MOST:
                finalHeight = Math.min(heightSize,viewHeight);
                打破;
            案例View.MeasureSpec.UNSPECIFIED:
                finalHeight = viewHeight;
                打破;
            默认:
                finalHeight = heightSize;
                打破;
        }        setMeasuredDimension(finalWidth,finalHeight);
    }
    私人无效measureScrapChild(RecyclerView.Recycler回收,INT位置,诠释widthSpec,诠释heightSpec,INT [] measuredDimension){        查看查看= recycler.getViewForPosition(位置);        如果(查看!= NULL){            RecyclerView.LayoutParams p值=(RecyclerView.LayoutParams)view.getLayoutParams();            INT childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,getPaddingLeft()+ getPaddingRight(),p.width);
            INT childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,getPaddingTop()+ getPaddingBottom(),p.height);            view.measure(childWidthSpec,childHeightSpec);            measuredDimension [0] = view.getMeasuredWidth()+ p.leftMargin + p.rightMargin;
            measuredDimension [1] = view.getMeasuredHeight()+ p.bottomMargin + p.topMargin;            矩形decoratorRect =新的矩形();
            calculateItemDecorationsForChild(查看,decoratorRect);
            measuredDimension [0] + = decoratorRect.left;
            measuredDimension [0] + = decoratorRect.right;
            measuredDimension [1] + = decoratorRect.top;
            measuredDimension [1] + = decoratorRect.bottom;            recycler.recycleView(视图);
        }
    }
}

I try to solve the following:

  • using RecyclerView
  • with GridLayoutManager
  • with fixed cell-widths
  • recyclerview resizing only to the necessary height (wrap_content)

I try to use the following code, the problem is that it doesn't work, and I haven't found any working example not mentioning to redraw properly when orientation changes.

public class AutofitRecyclerView extends RecyclerView {
    private MyGridLayoutManager manager;
    private int columnWidth = -1;

    public AutofitRecyclerView(Context context) {
        super(context);
        init(context, null);
    }

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

    public AutofitRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        if (attrs != null) {
            int[] attrsArray = {
                    android.R.attr.columnWidth
            };
            TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
            columnWidth = array.getDimensionPixelSize(0, -1);
            array.recycle();
        }

        manager = new MyGridLayoutManager(getContext(), 1);
        setLayoutManager(manager);
    }

    @Override
    protected void onMeasure(int widthSpec, int heightSpec) {
        super.onMeasure(widthSpec, heightSpec);
        if (columnWidth > 0) {

            int mw = getMeasuredWidth();

            int spanCount = Math.max(1, mw / columnWidth);
            manager.setSpanCount(spanCount);
        }

        int numOfFullRows = manager.getItemCount() / manager.getSpanCount();

        if(manager.getItemCount() % manager.getSpanCount() > 0)
        {
            numOfFullRows++;
        }

        if(getChildCount() > 0) {
            int h = 0;
            try {
                h = manager.getChildAt(0).getMeasuredHeight();
            } catch (Exception e) {
                e.printStackTrace();
            }

            if(h != 0) {
                getLayoutParams().height = numOfFullRows * h;
            }
        }
    }
}

解决方案

Based on the code that connector published I came up with the following solution that supports different row / column sizes (though I have admittedly not tested that), takes the sizes of the item decorations into account and handles the different measure modes properly.

Here is the code:

import android.content.Context;
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;

public class WrappableGridLayoutManager extends GridLayoutManager {

    public WrappableGridLayoutManager(Context context, int spanCount) {
        super(context, spanCount);
    }

    private int[] measuredSize = new int[2];

    @Override
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
        final int widthMode = View.MeasureSpec.getMode(widthSpec);
        final int heightMode = View.MeasureSpec.getMode(heightSpec);
        final int widthSize = View.MeasureSpec.getSize(widthSpec);
        final int heightSize = View.MeasureSpec.getSize(heightSpec);

        int spanWidth = 0;
        int spanHeight = 0;

        int viewWidth = 0;
        int viewHeight = 0;

        int spanCount = getSpanCount();

        for (int i = 0; i < getItemCount(); i++) {

            measureScrapChild(recycler, i, View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), measuredSize);

            if (i % spanCount == 0) {
                spanWidth = measuredSize[0];
                spanHeight = measuredSize[1];
            } else {
                if (getOrientation() == VERTICAL) {
                    spanWidth += measuredSize[0];
                    spanHeight = Math.max(spanHeight, measuredSize[1]);
                } else {
                    spanWidth = Math.max(spanWidth, measuredSize[0]);
                    spanHeight += measuredSize[1];
                }
            }

            if (i % spanCount == spanCount - 1 || i == getItemCount() - 1) {
                if (getOrientation() == VERTICAL) {
                    viewWidth = Math.max(viewWidth, spanWidth);
                    viewHeight += spanHeight;
                } else {
                    viewWidth += spanWidth;
                    viewHeight = Math.max(viewHeight, spanHeight);
                }
            }
        }

        int finalWidth;
        int finalHeight;

        switch (widthMode) {
            case View.MeasureSpec.EXACTLY:
                finalWidth = widthSize;
                break;
            case View.MeasureSpec.AT_MOST:
                finalWidth = Math.min(widthSize, viewWidth);
                break;
            case View.MeasureSpec.UNSPECIFIED:
                finalWidth = viewWidth;
                break;
            default:
                finalWidth = widthSize;
                break;
        }

        switch (heightMode) {
            case View.MeasureSpec.EXACTLY:
                finalHeight = heightSize;
                break;
            case View.MeasureSpec.AT_MOST:
                finalHeight = Math.min(heightSize, viewHeight);
                break;
            case View.MeasureSpec.UNSPECIFIED:
                finalHeight = viewHeight;
                break;
            default:
                finalHeight = heightSize;
                break;
        }

        setMeasuredDimension(finalWidth, finalHeight);
    }


    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) {

        View view = recycler.getViewForPosition(position);

        if (view != null) {

            RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();

            int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), p.width);
            int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), p.height);

            view.measure(childWidthSpec, childHeightSpec);

            measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
            measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;

            Rect decoratorRect = new Rect();
            calculateItemDecorationsForChild(view, decoratorRect);
            measuredDimension[0] += decoratorRect.left;
            measuredDimension[0] += decoratorRect.right;
            measuredDimension[1] += decoratorRect.top;
            measuredDimension[1] += decoratorRect.bottom;

            recycler.recycleView(view);
        }
    }
}

这篇关于与GridLayoutManager试图解决WRAP_CONTENT RecyclerView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆