I am having an issue with GridLayoutManger
setSpanSizeLookup
, when an orientation of activity changes, I am changing the span count while checking if the specific position is some sort of type, this works perfectly on orientation change, my only problem is, I'm using zxing
library to do barcode scanning, whenever a button
is clicked I'm opening the zxing
default intent and retrieve date from it, however when zxing
is opening it goes to landscape
and my current activity orientation is portrait
this gives me the IllegalArgumentException
that the layout manage throws when only opening the Xzing
intent, the crash log is as this
java.lang.IllegalArgumentException: Item at position 0 requires 2 spans but GridLayoutManager has only 1 spans.
this problem doesn't occur if i rotate the phone, only happens when I launch the Xzing
intent, i couldn't really figure out how how I solve this issue as its bugging me. here is my spanSizeLookup
-
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return adapter.getHolders().get(position).getLabelHolder() != null ? getResources().getInteger(R.integer.span) : 1;
}
});
the span
is base on screen size so it can be 1-2, 2-3 and 3-4. i repeat this doesn't give me any error on orientation change, only the error occur when I open the zxing
P.S if i open zxing intent
while my activity is on landspace
the crash wont occur.
Edit
it seems like only launching the zxing
default intent causing this issue, I'm having an activity
where it goes landscape
after it launches and the exception
didn't occur, as a workaround i did, was that i created an activity
that handles the barcode
scanning with a delay of 1 second to launch the intent
as if i didn't do that, it will throw the same exception
.
Edit 2
I just found that, even without setSpanSpizeLookup the crash still occurs. by just calling manager.setSpanCount(getResources().getInteger(R.integer.span))
Here's the source code that throws the exception in GridLayoutManager.layoutChunk()
final int spanSize = getSpanSize(recycler, state, pos);
if (spanSize > mSpanCount) {
throw new IllegalArgumentException("Item at position " + pos + " requires " +
spanSize + " spans but GridLayoutManager has only " + mSpanCount
+ " spans.");
}
Is your spanSize greater than your spanCount? Try to debug and probably change your spanCount and see how it works.
---- Updated ----
There're couple ways to switch between list and grid.
Only changing the spanCount.
You have to call LayoutManager.requestLayout()
after you change your spanCount. Otherwise your app may crash.
Only changing the SpanSizeLookUp.
private class CustomSpanSize extends GridLayoutManager.SpanSizeLookup {
private static final int LIST_SPAN_SIZE = 1;
private static final int GRID_SPAN_SIZE = 2;
private int mSpanSize = LIST_SPAN_SIZE;
public void asList() {
mSpanSize = LIST_SPAN_SIZE;
}
public void asGrid() {
mSpanSize = GRID_SPAN_SIZE;
}
@Override
public int getSpanSize(int position) {
return mSpanSize;
}
}
and use it like that
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLayoutManager = new GridLayoutManager(this, 2);
mCustomSpanSize = new CustomSpanSize();
mLayoutManager.setSpanSizeLookup(mCustomSpanSize);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(mLayoutManager);
...
}
public void someFunction() {
if (changed) {
mCustomSpanSize.asList();
} else {
mCustomSpanSize.asGrid();
}
// use this to update the layout
mAdapter.notifyDataSetChanged();
// or you can use this to update the layout
mLayoutManager.requestLayout();
}
this way won't crash even you forget to call notifyDataSetChanged
or requestLayout