-
-
Save ArthurSav/5f80e19d9ba6d562fbd5 to your computer and use it in GitHub Desktop.
package com.inperson.android.utils.leastview; | |
import android.content.Context; | |
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[] mMeasuredDimension = 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 width = 0; | |
int height = 0; | |
for (int i = 0; i < getItemCount(); i++) { | |
measureScrapChild(recycler, i, | |
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), | |
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), | |
mMeasuredDimension); | |
if (getOrientation() == HORIZONTAL) { | |
if (i % getSpanCount() == 0) { | |
width = width + mMeasuredDimension[0]; | |
} | |
if (i == 0) { | |
height = mMeasuredDimension[1]; | |
} | |
} else { | |
if (i % getSpanCount() == 0) { | |
height = height + mMeasuredDimension[1]; | |
} | |
if (i == 0) { | |
width = mMeasuredDimension[0]; | |
} | |
} | |
} | |
switch (widthMode) { | |
case View.MeasureSpec.EXACTLY: | |
width = widthSize; | |
case View.MeasureSpec.AT_MOST: | |
case View.MeasureSpec.UNSPECIFIED: | |
} | |
switch (heightMode) { | |
case View.MeasureSpec.EXACTLY: | |
height = heightSize; | |
case View.MeasureSpec.AT_MOST: | |
case View.MeasureSpec.UNSPECIFIED: | |
} | |
setMeasuredDimension(width, height); | |
} | |
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; | |
recycler.recycleView(view); | |
} | |
} | |
} |
I used this to Wrap the Grid of RecyclerView Working fine
mMultiSelectView.setLayoutManager(new WrappableGridLayoutManager(mContext, 2));
But problem is when I used SpaceItemDecoration its cutting the item
mMultiSelectView.addItemDecoration(new SpaceItemDecoration(20, LinearLayoutManager.VERTICAL));
Help me with this, Thanks.
Great Thanks
@riyazMuhammad please could u describe where exctly set
- setMeasuredDimension(width, height+10);
as i set in onMesure but no effect
if child layout has that Custom Square Image View
List size = measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(widthSize / getSpanCount(), widthMode),
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED));
Hi
What is the license of your code ?
Works perfectly
Thanks
//Method threw 'java.lang.IndexOutOfBoundsException' :Invalid item position 0(0). Item count:0 in measureScrapChild() at line:
View view = recycler.getViewForPosition(position);
//Method threw 'java.lang.IndexOutOfBoundsException' :Invalid item position 0(0). Item count:0 in measureScrapChild() at line:
View view = recycler.getViewForPosition(position);
With Android M got this:
//Method threw 'java.lang.IndexOutOfBoundsException' :Invalid item position 0(0). Item count:0 in measureScrapChild() at line:
View view = recycler.getViewForPosition(position);
//Method threw 'java.lang.IndexOutOfBoundsException' :Invalid item position 0(0). Item count:0 in measureScrapChild() at line:
View view = recycler.getViewForPosition(position);
to fix
:Invalid item position 0(0). Item count:0 in measureScrapChild()
change View view = recycler.getViewForPosition(position); to this code:
View view = null;
try {
view = recycler.getViewForPosition(position);
} catch (Exception ex) {
// try - catch is needed since support library version 24
}
Hello, thx for this snippet, but i have a problem - recycler view binding ALL his views on initialisation and again on scroll
Kotlin version with support for different spanCount:
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.Recycler
import com.baziliqo.app.bar.utils.takeIfInstance
class WrappableGridLayoutManager(context: Context?, val preferedSpanCount: Int, @RecyclerView.Orientation orientation: Int = RecyclerView.VERTICAL) :
GridLayoutManager(context, preferedSpanCount, orientation, false) {
private val mMeasuredDimension = IntArray(2)
var measuredWidth = 0
var measuredHeight = 0
override fun onMeasure(recycler: Recycler, state: RecyclerView.State, widthSpec: Int, heightSpec: Int) {
val suitableSpanCount = preferedSpanCount.coerceAtMost(itemCount)
if (spanCount != suitableSpanCount) {
spanCount = suitableSpanCount
return
}
val widthMode = View.MeasureSpec.getMode(widthSpec)
val heightMode = View.MeasureSpec.getMode(heightSpec)
val widthSize = View.MeasureSpec.getSize(widthSpec)
val heightSize = View.MeasureSpec.getSize(heightSpec)
measuredWidth = 0
measuredHeight = 0
for (i in 0 until itemCount) {
measureScrapChild(
recycler, i,
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension
)
if (orientation == HORIZONTAL) {
if (i % spanCount == 0) {
measuredWidth += mMeasuredDimension[0]
}
if (i < spanCount) {
measuredHeight += mMeasuredDimension[1]
}
} else {
if (i % spanCount == 0) {
measuredHeight += mMeasuredDimension[1]
}
if (i < spanCount) {
measuredWidth += mMeasuredDimension[0]
}
}
}
when (widthMode) {
View.MeasureSpec.EXACTLY -> measuredWidth = widthSize
View.MeasureSpec.AT_MOST, View.MeasureSpec.UNSPECIFIED -> {
}
}
when (heightMode) {
View.MeasureSpec.EXACTLY -> measuredHeight = heightSize
View.MeasureSpec.AT_MOST, View.MeasureSpec.UNSPECIFIED -> {
}
}
setMeasuredDimension(measuredWidth, measuredHeight)
}
private fun measureScrapChild(recycler: Recycler, position: Int, widthSpec: Int, heightSpec: Int, measuredDimension: IntArray) {
try {
var view = recycler.getViewForPosition(position) ?: return
val p = view.layoutParams as RecyclerView.LayoutParams
val childWidthSpec = ViewGroup.getChildMeasureSpec(
widthSpec,
paddingLeft + paddingRight, p.width
)
val childHeightSpec = ViewGroup.getChildMeasureSpec(
heightSpec,
paddingTop + paddingBottom, p.height
)
view.measure(childWidthSpec, childHeightSpec)
measuredDimension[0] = view.measuredWidth + p.leftMargin + p.rightMargin
measuredDimension[1] = view.measuredHeight + p.bottomMargin + p.topMargin
recycler.recycleView(view)
} catch (e: Exception) {
}
}
}
Good one buddy.
I tried it with the items being a textview and compound drawables on it. So I was seeing a little scroll and then top most and bottom most rows were being cut a little. so did the following
And now it's all fine. Hope it helps someone.