I have a reyclerview in which every time I add an item I add it at index 0, Usually when you add an item a given index you can do it like so
mAdapter.add(0, item)
mAdapter.notifyItemChanged(0)
the problem is the item will be added to index 0 but the user will have to scroll to view it, of course, there is a solution which is by simply doing the following
messageAdapter.add(0, item)
messageAdapter.notifyDataSetChanged()
the problem here is that by calling "notifyDataSetChanged()" the item will appear all of sudden inside the list which I don't like I want to have a nice and smooth animation for when the item is added, another solution is to manually smooth scroll the recyclerView whenever an item is added using our first code, this solution is the best but it has some problems.
when the user is viewing item at index 999 and a new item is added the view will be scrolled to index 0 which can be kind of annoying for the user, the solution is simple for this problem, we can check if the item at index 0 is visible if it is, then scroll to index 0, this is the perfect solution for my problem.
So my question is, is there any other way to implement the functionality that I want to achieve without having to do that work? I would like to know what the simplest way is, thank you in advance!
Try using diff util it will be better for performance for updating recyclerview
https://blog.mindorks.com/the-powerful-tool-diff-util-in-recyclerview-android-tutorial
Related
I have been battling with RecyclerView for the last 2 days. Unlike any time in the past, I want to have swipe to dismiss functionality.
I followed
this guide
The only difference here that I have implemented is instead of using a predefined array for input, I have an API response to populate the data. All that seems to be good, when I open the recyclerview the items populate as they should. In the order that they should.
Here is where the fun begins. If I try to swipe to dismiss the first item I get an IndexOutOfBounds error. Thats cute, searching I found that some choose to set a new List based on the first list, remove the item and then re-assign the original list to the new list. notifyDataSetChanged() when done. No more error BUT no animation of the recycler view to bring the 2nd item to the top of the list. any time notifyDataSetChanged() is called the list does NOT move. I scroll down and back up and the item is back. Or so I thought.
After playing with this for a while I noticed that while the information in the first item appeared to the be the original first item, its got an ID of the second item in the list and the last item in the view is now missing.
Here is an example:
text = Fox id = a
text = Dog id = b
text = Pig id = c
I swipe dismiss 1 from the list, this is what the UI shows
text = Fox id = b
text = Dog id = c
Lots of code to embed here and its throwing errors trying to do so, gist is here https://gist.github.com/baggednismo/2840d0f777438d29673bc29096153970
Try removing setHasStableIds(true) and the overridden getItemId() from your adapter.
You're telling the RecyclerView that the nth view will always represent the same item in the list, and it's getting upset when you remove one of the items.
(I just tried a very simplified example with setHasStableIds(true) and got a similar exception; it worked fine when I removed it and the getItemId())
Note that your call to notifyItemDeleted() is preferable to replacing the entire list, but if you did want or need to replace the entire list, you should look at using DiffUtil to determine and make the appropriate changes to the list, and it will do all the cool animation if the same items are still present.
If you want to see my example, it's at https://gist.github.com/javadude/dec1862b075338790f023b42e01fd953 (but it's in kotlin)
#Scott Stanchfield was very much correct on his input. The noted changes in his comments and answer cleaned up the view to help me find the actual view related issue. The suggestions are still implemented and are part of the solution.
onBindViewHolder() created the view of items of which it was creating the line items based on the original API response order and not the list order recyclerview was handling. onBindViewHolder() is called each time a new item is to appear in the list on scroll and this was the problem. This works fine on the very first inflation of the list however once the item was removed and scrolling back to the top the first item appeared to be the item dismissed.
Original:
KitchenOrdersResponse.Item mItem = mKitchenOrdersResponse.getItems().get(i);
Resolution:
KitchenOrdersResponse.Item mItem = mItems.get(i);
If the recyclerview has a list of items and I want to go to a specific row immediately when user enters the UI, so I don't want the user to see it scroll to reach that row. Is it achievable?
Thanks.
You can use method scrollToPositionWithOffset (int position, int offset)
Scroll to the specified adapter position with the given offset from
resolved layout start.
See documentation
Example:
//Scroll to item position 2 with offset 0
RECYCLERVIEW_LAYOUT_MANAGER.scrollToPositionWithOffset(2, 0);
Hope this will help~
I would say it is impossible.
RecyclerView#scrollToPosition causes sort of animation because it does not know the height of all rows initially. Not all items are loaded immediatly but one by one as you scroll down the list.
I use ListView and I solved the issue by calling setSelection(position)
i am trying to add some animations to my Recyclerview. So far everything works great, but i have reached on problem i don't have an answer to.
I have a List where the user should be able to select only one Item. When an item is selected an animation starts and a checked box appears. Now if another item is selected it should also play this animation (This Part works) but it should also remove the checkbox from previous selected one with an animation (This part does not work).
My Problem is that i do not have a clue how to get the adapterPosition of the previous selected item.
I am thankful for any help
So i solved it, maybe someday someone will stumble upon this question, so here is the answer.
The Recyclerview adapter method getAdapterPosition() returns the sam value as the index in the ArrayList given to the Adapter.
All you have to do is fetch the index of the item you want to manipulate and then you can work with that.
If some one needs more details, then post a comment.
BACKGROUND:
I have a grid of 36 buttons, lets say a 6 rows & 6 columns numbered 1 to 36, displayed 2 rows at a time via a GridView and custom Adapter
The grid displays fine, and all of the scrolling works properly.
QUESTION:
I want to be able to click on an item, have it removed from the grid and the remain items shuffle up into place. Currently I am able to disable the item disabled, set its visibility to INVISIBLE or GONE, but none of these will actually remove it from the display.
Suggestions?
Specifically, you need to remove the corresponding object from the data set of the underlying adapter and then call adapter.notifyDataSetChanged(). This isn't going to provide you with an animation, though, if that was part of this question.
It may be interesting to try a tween animation for the item in question and then finally remove it from your adapter at the end. I'm not well-versed in animation, so I'm not sure how well this will work in an AdapterView.
You should be able to update the adapter, and then call notifyDataSetChanged to force the grid view to be updated.
I have an android-app with a listview in an activity. The listview has, if I call it so, three data states.
no data loaded from inet -> only one dummy item is visible, saying that data is loading;
data is loaded and shown in list;
one listitem is clicked and now shows more information for this listitem (so it is increased in its height).
On every state change (1 -> 2, 2 -> 3), I call notifyDataSetChanged() on this ListAdapater.
This causes the listview to scroll down to the last item. This is ugly in the first transition and even more ugly in the second because the clicked list item is now out of focus.
As I can see, this happens with a google g1 with android 1.6. An htc touch with the same sdk acts like desired (I will try to figure it out with some more devices).
To avoid this, I tried to read out getScrollY() and set this value back. but this returns 0. The reason for this return value I already found on stackoverflow in other questions.
Has anyone else seen this problem? Why does the listview scroll to the last item? It was mentioned that listview keeps track of the scroll position. but it seems that it does not in my case.
Or maybe I am calling the wrong refresh method? Is notifyDataSetChanged the correct one?
I believe you want:
listview.setTranscriptMode(ListView.TRANSCRIPT_MODE_DISABLED);