using notifyItemRemoved or notifyDataSetChanged with RecyclerView in Android - android

I am creating a list of cards to display using the RecyclerView, where each card has a button to remove that card from the list.
When i use notifyItemRemoved() to remove the card in the RecyclerView, it removes the item and animates fine but the data in the list is not updated correctly.
If instead of that, i switch to the notifyDataSetChanged() then the items in list are removed and updated correctly, but then the cards dont animate.
Does someone has any experience in using the notifyItemRemoved() and know why it behaves differently than notifyDataSetChanged?
Here is some peiece of code that i am using:
private List<DetectedIssue> issues = new ArrayList<DetectedIssue>();
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
if(position >0){
RiskViewHolder riskHolder = (RiskViewHolder)holder;
final int index = position - 1;
final DetectedIssue anIssue = issues.get(index);
riskHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
int index = issues.indexOf(anIssue);
issues.remove(anIssue);
notifyItemRemoved(index);
//notifyDataSetChanged();
} catch (SQLException e) {
e.printStackTrace();
}
}
});
}
}
#Override
public int getItemCount() {
return (issues.size()+1);
}

Use notifyItemRangeChanged(position, getItemCount()); after notifyItemRemoved(position);
You don't need to use index, just use position. See code below.
private List<DetectedIssue> issues = new ArrayList<DetectedIssue>();
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
if(position >0){
RiskViewHolder riskHolder = (RiskViewHolder)holder;
riskHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
issues.remove(position);
notifyItemRemoved(position);
//this line below gives you the animation and also updates the
//list items after the deleted item
notifyItemRangeChanged(position, getItemCount());
} catch (SQLException e) {
e.printStackTrace();
}
}
});
}
}
#Override
public int getItemCount() {
return issues.size();
}

Tried
public void removeItem(int position) {
this.taskLists.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, getItemCount() - position);
}
and working like a charm.

my mistake ,
notifyItemChanged(position) is helpless,the item of position can be removed ,and the item of position+1 is fine,but the items start from position+2,you will get an Exception, please use notifyItemRangeChanged(position,getItemCount());
after notifyItemRemoved(position);
like this:
public void removeData(int position) {
yourdatalist.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position,getItemCount());
}

Use this it is working perfectly.
issues.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, issues.size());

As #pskink suggested it was supposed to be (index+1) in my case with notifyItemRemoved(index+1), probably because i am reserving the top index i.e. position=0 for a header.

**my solution looks like this**
this way is unnecessary to use the heavy method:
//notifyItemRangeChanged(xx,xx)
/**
*
* recyclerView的item中的某一个view,获取其最外层的viewParent,也就是item对应的layout在adapter中的position
*
* #param recyclerView
* #param view:can be the deep one inside the item,or the item itself .
* #return
*/
public static int getParentAdapterPosition(RecyclerView recyclerView, View view, int parentId) {
if (view.getId() == parentId)
return recyclerView.getChildAdapterPosition(view);
View viewGroup = (View) view.getParent();
if (viewGroup != null && viewGroup.getId() == parentId) {
return recyclerView.getChildAdapterPosition(viewGroup);
}
//recursion
return getParentAdapterPosition(recyclerView, viewGroup, parentId);
}
//wherever you set the clickListener .
holder.setOnClickListener(R.id.rLayout_device_item, deviceItemClickListener);
holder.setOnLongClickListener(R.id.rLayout_device_item, deviceItemLongClickListener);
#Override
public boolean onLongClick(View v) {
final int position = ViewUtils.getParentAdapterPosition(rVDevicesList, v, R.id.rLayout_device_item);
return true;
}

In my case I use Content Provider and a Custom RecyclerView Adapter with Cursor. This line of code is where you notify:
getContext().getContentResolver().notifyChange(uri, null);
Assuming In your recyclerView adapter (Delete Button):
Uri currentUri = ContentUris.withAppendedId(DatabaseContract.ToDoEntry.CONTENT_URI_TODO, id);
int rowsDeleted = mContext.getContentResolver().delete(currentUri, null, null);
if (rowsDeleted == 0) {
Log.d(TAG, "onClick: Delete failed");
} else {
Log.d(TAG, "onClick: Delete Successful");
}
And in your Database Provider:
case TODO_ID:
selection = DatabaseContract.ToDoEntry._ID + "=?";
selectionArgs = new String[] {String.valueOf(ContentUris.parseId(uri))};
rowsDeleted = database.delete(DatabaseContract.ToDoEntry.TODO_TABLE_NAME, selection, selectionArgs);
if (rowsDeleted != 0){
getContext().getContentResolver().notifyChange(uri, null);
}
return rowsDeleted;

You can use getAdapterPosition() from the RecyclerView.ViewHolder
getLayoutPosition() provides the exact position of item in the layout and code is
holder.removeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Position for remove
int modPosition= holder.getAdapterPosition();
//remove item from dataset
numbers.remove(modPosition);
//remove item from recycler view
if(numbers.isEmpty())
notifyDataSetChanged ()
else
notifyItemRemoved(modPosition);
}
});

Related

How to hide/display specific RecyclerView item?

I have a contacts list RecyclerView, where the first item (position 0) holds the user's details. When the search icon in the toolbar is pressed, I want that entry to be hidden from the user.
I've tried using setVisibility(View.GONE) on it, and, although the entry is hidden, the space it occupied was still there, much like setting setVisibility(View.INVISIBLE). How can I toggle the visibility of this specific entry to VISIBLE/GONE in my RecyclerView, or how can I set its height only to 0dp?
EDIT:
My xml is quite simple, it comprises of simply a recyclerView and a FAB. My adapter code is as below.
ContactsAdapter(
Context context,
List<LinphoneContact> contactsList,
ContactViewHolder.ClickListener clickListener,
SelectableHelper helper) {
super(helper);
mContext = context;
updateDataSet(contactsList);
mClickListener = clickListener;
}
#NonNull
#Override
public ContactViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// For the first position only, use the user's own contact card
// For all the rest, use the contact card
switch (viewType) {
case USER_CARD_VIEW:
View userCard =
LayoutInflater.from(parent.getContext())
.inflate(R.layout.contacts_user_card, parent, false);
return new ContactViewHolder(userCard, mClickListener);
case CONTACT_CARD_VIEW:
View contactCard =
LayoutInflater.from(parent.getContext())
.inflate(R.layout.contact_cell, parent, false);
return new ContactViewHolder(contactCard, mClickListener);
}
return null;
}
#Override
public void onBindViewHolder(#NonNull ContactViewHolder holder, int position) {
// Remove the user's card when searching contacts - DOES NOT WORK, MAKES ALL FIRST ITEMS
// INVISIBLE
// if (position == 0) {
// if (mIsSearchMode) holder.itemView.setVisibility(View.GONE);
// else holder.itemView.setVisibility(View.VISIBLE);
// }
if (position != 0) {
LinphoneContact contact = (LinphoneContact) getItem(position - 1);
holder.name.setText(contact.getFullName());
if (!mIsSearchMode) {
String fullName = contact.getFullName();
if (fullName != null && !fullName.isEmpty()) {
holder.separatorText.setText(String.valueOf(fullName.charAt(0)));
}
}
// Separator as in the big capital letter on the left to indicate sections
holder.separator.setVisibility(
mIsSearchMode
|| (getPositionForSection(getSectionForPosition(position))
!= position)
? View.GONE
: View.VISIBLE);
holder.linphoneFriend.setVisibility(
contact.isInFriendList() ? View.VISIBLE : View.GONE);
ContactAvatar.displayAvatar(contact, holder.avatarLayout);
boolean isOrgVisible = LinphonePreferences.instance().isDisplayContactOrganization();
String org = contact.getOrganization();
if (org != null && !org.isEmpty() && isOrgVisible) {
holder.organization.setText(org);
holder.organization.setVisibility(View.VISIBLE);
} else {
holder.organization.setVisibility(View.GONE);
}
holder.delete.setVisibility(isEditionEnabled() ? View.VISIBLE : View.INVISIBLE);
holder.delete.setChecked(isSelected(position));
// } else {
// // TODO - user's card should have whole and voicemail onClick listeners
}
// Log.d("contactsAdapter", "Position: " + position);
// Log.d("contactsAdapter", "Section for position: " +
// getSectionForPosition(position));
// Log.d(
// "contactsAdapter",
// "The other thingy: " +
// getPositionForSection(getSectionForPosition(position)));
}
// +1 item count to account for user's contact card
#Override
public int getItemCount() {
return mContacts.size() + 1;
}
public Object getItem(int position) {
if (position >= getItemCount()) return null;
return mContacts.get(position);
}
public void setIsSearchMode(boolean set) {
mIsSearchMode = set;
}
[...]
#Override
public int getItemViewType(int position) {
return position == 0 ? USER_CARD_VIEW : CONTACT_CARD_VIEW;
}
Essentially, I don't add the first item to my list of items, but instead I add it to the recyclerView, and shift my list of items by one position up.
although the entry is hidden, the space it occupied was still there
may be because you are hiding the child but its parent is still there with its height or padding given
How can I toggle the visibility of this specific entry to VISIBLE/GONE in my RecyclerView
Toggle the visibility of parent
In your onBindViewHolder
#Override
public void onBindViewHolder(#NonNull MyViewHolder viewHolder, int i) {
if (isButtonPressed) {
viewHolder.parentViewId.setVisibility(View.GONE);
}else {
viewHolder.parentViewId.setVisibility(View.VISIBLE);
}
}
Create a public boolean isButtonPressed; and when you press the button make it true and call adapter.notifyDataSetChanged();

Why I'm getting recyclerview's item position as "-1"?

I'm having a very strange error . Basically I'm trying to delete recyclerview items on LongClick but in some cases I'm getting adapter position as -1.
My Code:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Message message = mMessages.get(position);
holder.setMessage(message.getMessage());
holder.msgContainer.setOnLongClickListener(view -> {
int position = holder.getAdapterPosition();
mMessages.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mMessages.size());
return false;
});
}
}
}
From the docs: RecyclerView does not handle any adapter updates until the next layout traversal. This may create temporary inconsistencies between what user sees on the screen and what adapter contents have.
This is a common issue, just wrap your call in an if statement checking if the position isn't -1.
if (getAdapterPosition() != - 1)
getAdapterPosition() return -1.It means Adapter gets a NO_POSITION,and it always happened when you call method like notifyDataSetChanged(). we always use position like this
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
Message message = mMessages.get(position);
holder.setMessage(message.getMessage());
holder.msgContainer.setOnLongClickListener(view -> {
//you can use the position parameter directly,just set it as final
mMessages.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mMessages.size());
return false;
});
}

How to highlight the first row of RecyclerView by default and then remove highlight as and when other rows are selected?

I am trying to load a list in RecyclerView and show the first row of the list as selected. I have achieved it using the following code:
#Override
public void onBindViewHolder(NavigationDrawerAdapter.ViewHolder holder, final int position) {
if (!mNavClassrooms.get(position).equals("")) {
holder.mTextViewClassroom.setText(mNavClassrooms.get(position)); // Setting the Text with the array of our Titles
holder.mRelLayClassroom.setSelected(mSelectedItems.get(position, false));
/*
The following code was written to make the first item in the Classroom list as selected.
It leads to the item always being selected and hence has been commented out.
*/
if(position == 0 && intOldSelectedItem == -1){
holder.mRelLayClassroom.setSelected(mSelectedItems.get(position, true));
intOldSelectedItem = 0;
mSelectedView = holder.mRelLayClassroom.getChildAt(position);
mSelectedItems.put(position, true);
}
else{
holder.mRelLayClassroom.setSelected(mSelectedItems.get(position, false));
}
} else {
holder.mTextViewClassroom.setText("No classes found");
holder.mTextViewClassroom.setPadding(40, 0, 0, 0);
}
holder.mRelLayClassroom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mSharedPreferences = mContext.getSharedPreferences(Constants.AAPREFERENCES, Context.MODE_PRIVATE);
String strClassroomValue = mNavClassrooms.get(position);
int strClassroomName = mNavClassroomNames.get(position);
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString(Constants.CLASSROOM_VALUE, strClassroomValue);
editor.putInt(Constants.CLASSROOM_NAME, strClassroomName);
editor.commit();
/*
We are storing the position of the selected row in the SparseBooleanArray.
We delete it in case another row has been selected.
*/
if (mSelectedItems.get(position, false)) {
/*
Do nothing
*/
} else {
mSelectedItems.put(position, true);
/*
Making sure that the delete code is called only if some view is selected
*/
if (mSelectedView != null) {
mSelectedView.setSelected(false);
mSelectedItems.delete(intOldSelectedItem);
view.setSelected(false);
}
mSelectedView = view;
intOldSelectedItem = position;
view.setSelected(true);
}
}
However, now the first row stays selected always. I am unable to deselect it. I cannot seem to get this working.
I referred to the following answer to achieve most of this functionlaity.
https://stackoverflow.com/a/29984220/2186220
Any help will be appreciated.
I'm not answering your question by posting a fixed version of your onBindViewHolder method since it's kinda hard to understand and we don't know how the rest of your adapter looks like. So following a RecyclerView Adapter which does what you want: Selecting the first row by default and deselecting it once a other row is selected.
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
// ... other fields
// default selection position is the first one
private int selectedPosition = 0;
// ... constructor etc.
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
if(position == selectedPosition){
holder.itemView.setSelected(true);
} else {
holder.itemView.setSelected(false);
}
// Actual selection / deselection logic
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int currentPosition = holder.getLayoutPosition();
if(selectedPosition != currentPosition){
// Temporarily save the last selected position
int lastSelectedPosition = selectedPosition;
// Save the new selected position
selectedPosition = currentPosition;
// update the previous selected row
notifyItemChanged(lastSelectedPosition);
// select the clicked row
holder.itemView.setSelected(true);
}
}
});
// other adapter code
}
// other adapter stuff like onCreateViewHolder, getItemCount, ViewHolder etc.
}
Note: I guess there's no need to use a SparseBooleanArray so simply remove it and replace it with the int field used in the example above.
Initialize your
int intOldSelectedItem=0 and keep one boolean isVisible= false;
And do it as below:
if (holder.getPosition() == intOldSelectedItem) {
if (isVisible) {
//background for selected item
} else {
//background for unselected item
}
} else {
//background for unselected item
}
holder.mRelLayClassroom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (intOldSelectedItem== holder.getPosition()) {
isVisible = !isVisible;
} else {
if (intOldSelectedItem!= 0) {
isVisible = false;
notifyItemChanged(intOldSelectedItem);
}
isVisible = true;
}
intOldSelectedItem= holder.getPosition();
notifyItemChanged(intOldSelectedItem);
}
});
I hope it might help you.
Add background selector to your ViewHolder layout.
Create your selector handler something like this:
public class SingleSelector {
private View oldVIew;
public void setSelection(View newView) {
if (oldVIew == null) {
newView.setSelected(true);
oldVIew = newView;
} else {
oldVIew.setSelected(false);
newView.setSelected(true);
oldVIew = newView;
}
}
}
Set default selection when you need it:
#Override
public void onBindViewHolder(SimpleViewHolder holder, int position) {
if (position == 0) {
singleSelector.setSelection(holder.itemView);
}
}
In your ViewHolder add listener to itemView and pass it to the handler:
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
singleSelector.setSelection(itemView);
}
});

notifyDataSetChanged doesn't refresh RecyclerView

I have a weird problem. I switched to RecyclerView from ListView and I can't refresh or notify of change in my ListView. I tried calling Item.this.notifyDataSetChanged();
and other methods to refresh View but it doesn't work.
Instead RecyclerView is refreshed when I scroll(regardless of direction). How can I notify my RecyclerView when there is a change?
CODE:
#Override
public void onBindViewHolder(Ids holder, final int position) {
rowItemClass = (ListViewRow) rowItems.get(position);
Log.e("swag", "OYOYOYOYOYO");
if (Globals.isPlaying && Globals.pos == position) {
if (pausedSamePos == true) {
holder.pauseed_play.setVisibility(View.VISIBLE);
holder.playing_pause.setVisibility(View.GONE);
} else {
holder.pauseed_play.setVisibility(View.GONE);
holder.playing_pause.setVisibility(View.VISIBLE);
}
holder.song_currenttime_sb.setActive();
holder.song_duration.setVisibility(View.INVISIBLE);
holder.song_duration_sb.setVisibility(View.VISIBLE);
holder.seekbar.setActive();
} else {
holder.seekbar.setInactive();
holder.song_currenttime_sb.setInactive();
holder.song_icon.setImageResource(rowItemClass.getImageId());
holder.song_duration_sb.setVisibility(View.INVISIBLE);
holder.song_duration.setVisibility(View.VISIBLE);
holder.pauseed_play.setVisibility(View.GONE);
holder.playing_pause.setVisibility(View.GONE);
}
sharedPreference = new SharedPreference();
holder.song_duration.setTypeface(Globals
.getTypefaceSecondary(context));
holder.song_duration_sb.setTypeface(Globals
.getTypefaceSecondary(context));
holder.song_name.setTypeface(Globals.getTypefacePrimary(context));
holder.song_currenttime_sb.setTypeface(Globals
.getTypefaceSecondary(context));
holder.song_name.setText(rowItemClass.getTitle());
holder.song_duration.setText(rowItemClass.getDesc());
holder.song_duration_sb.setText(rowItemClass.getDesc());
holder.favorite.setTag(position);
holder.song_currenttime_sb.setTag(position);
holder.seekbar.setTag(position);
holder.clickRegister.setTag(position);
holder.song_icon.setTag(position);
holder.song_name.setTag(position);
holder.song_duration.setTag(position);
holder.song_duration_sb.setTag(position);
holder.more_options.setTag(position);
// int task_id = (Integer) holder.seekbar.getTag();
final Ids finalHolder = holder;
holder.clickRegister.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
if ((Globals.isPlaying.booleanValue())
&& (Globals.pos == position)) {
pausePlaying();
} else {
Globals.stopPlaying();
pausedSamePos = false;
Globals.pos = position;
Globals.isPlaying = true;
Item.this.notifyDataSetChanged();
Globals.mp = MediaPlayer.create(context, Integer
.valueOf(Item.this.songPos[position])
.intValue());
Globals.mp.start();
Globals.pos = position;
Globals.isPlaying = Boolean.valueOf(true);
Item.this.notifyDataSetChanged();
Globals.mp
.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(
MediaPlayer mpOnComplete) {
mpOnComplete.release();
Globals.isPlaying = false;
pausedSamePos = false;
Globals.isPlaying = Boolean
.valueOf(false);
finalHolder.menu_options
.startAnimation(new ViewExpandAnimation(
finalHolder.menu_options));
Item.this.notifyDataSetChanged();
}
});
}
} catch (Exception localException) {
}
}
});
holder.clickRegister
.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Globals.stopPlaying();
Item.this.notifyDataSetChanged();
return true;
}
});
}
I've been struggling hard with a similar issue, trying to handle a use-case where all of the adapter's content has to be replaced and the recycler-view should start from scratch: calling notifyDataSetChanged(), swapAdapter() with numerous combinations of subsequent calls to view/layout-manager invalidation requests resulted in nothing but a (seemingly) empty recycler-view. The view didn't even try to rebind the view holders.
What seemed to have worked it out is this hack-ish fix:
view.swapAdapter(sameAdapter, true);
view.scrollBy(0, 0);
As it turns out, scrollBy (even with 0 offsets) drives the recycler-view into laying out its views and executing the pending view-holders rebinding.
if you want notify your recycleListView just simple call notifyDataSetChanged(); in your class adapter. this is my method in my adapter class :
public class ListAdapter extends RecyclerView.Adapter<Listdapter.ViewHolder> {
....
private List<DesaObject> desaObjects= new ArrayList<DesaObject>();
public void setListObjects(List<DesaObject> desaObjects){
if(this.desaObjects.size()>0)
this.desaObjects.clear();
this.desaObjects = desaObjects;
notifyDataSetChanged();
}
....
public static class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final AppCompatTextView desa;
public ViewHolder(View view) {
super(view);
mView = view;
desa = (AppCompatTextView) view.findViewById(R.id.desa);
}
}
}
in your code you dont actually set or change your listObjects in the OnClickListener and please try notifyDataSetChanged(); instead of Item.this.notifyDataSetChanged();
I am not sure why is this, but notifyDataSetChanged(); didn't work. So I tried keeping track of changed items and refreshing them manually with notifyItemChanged(int); and so far it seems to be working. I am still not sure why refreshing whole RecyclerView didn't work.
Initialize your Adapter Again with changed data and use method 'swapadapter'. hope it helps.

Force RecyclerView to call onCreateViewHolder

I have a RecyclerView that can show items as list, small grids or large grid and this can be change at runtime. Depending on what style user chooses i inflate different layout in onCreateViewHolder.
I also use layoutManger.setSpanSizeLookUp() to switch between styles. My code looks like this
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
if(showType == ProductAdapter.SHOW_TYPE_SMALL_GRID)
return 1;
else
return columnCount; //show one item per row
}
});
#Override
public void onClick(View v) {
if(showType == ProductAdapter.SHOW_TYPE_SMALL_GRID)
showType = ProductAdapter.SHOW_TYPE_LARGE_GRID;
else
showType = ProductAdapter.SHOW_TYPE_SMALL_GRID;
int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
adapter = new ProductAdapter(getActivity(), productList, showType);
recyclerView.setAdapter(adapter);
layoutManager.scrollToPosition(firstVisibleItem);
}
The problem is to force onCreateViewHolder to be called I'm creating a new object every time user changes the style. Is there any other way?! to force onBindViewHolder() to be recalled. I simply use adapter.notifyDataSetChanged() How can i get something similar for onCreateViewHolder?
Any solution that doesn't uses multiple adapters is good enough!
What you need to do is:
Modify your Adapter:
Specify two types of Views that your Adapter can inflate:
private static final int LARGE_GRID_ITEM = -1;
private static final int SMALL_GRID_ITEM = -2;
Create a field that can store current type mCurrentType
Use your Adapter's getItemViewType. For example like this:
#Override
public int getItemViewType (int position) {
return mCurrentType;
}
In your createViewHolder use the viewType to decide what type of ViewHolder you need to create.
public final RecyclerView.ViewHolder createViewHolder (ViewGroup parent, int viewType){
if (viewType == LARGE_GRID_ITEM) {
//return large grid view holder
} else {
//return small grid view holder
}
}
Additionally you can create methods:
public void toggleItemViewType () {
if (mCurrentType == LARGE_GRID_ITEM){
mCurrentType = SMALL_GRID_ITEM;
} else {
mCurrentType = LARGE_GRID_ITEM;
}
}
public boolean displaysLargeGrid(){
return mCurrentType == LARGE_GRID_ITEM;
}
Modify the code you posted:
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
if (adapter.displaysLargeGrid()) {
return 1;
} else {
return columnCount; //show one item per row
}
}
});
#Override
public void onClick(View v) {
adapter.toggleItemViewType();
adapter.notifyDataSetChanged();
}
Its not the optimal choice but it's better to create a new Adapter, which will call onCreateViewHolder(). This way you can avoid your troubles, by the cost of very tiny performance issues.

Categories

Resources