与GridLayoutManager试图解决WRAP_CONTENT RecyclerView [英] RecyclerView with GridLayoutManager trying to solve wrap_content
本文介绍了与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屋!
查看全文