I'm trying to create a way to search inside a RecyclerView with animating the items that have been searched (hide the ones that don't meet the condition, and add the ones that do, if they're not already in).
Of course, the simplest way to search a RecyclerView is just filter the list and notifyDataSetChanged(). But most developers know that this call recreates the adapter from scratch, almost like it was just assigned. Also, this call doesn't give any feeling of the items being searched, as all the items appear at once.
I've tried creating some way where the items get added or removed to the list as they meet/not meet the condition, but this loses the order of the items. Unless of course you search where the item is in the main list, and put it where it belongs. Which makes the searching longer since you're searching again every insert.
I looked into using a TreeMap, but trees can't be accessed by index, only by key.
I've also used SparseArray, the only problem was the SparseArray doesn't tell you in what index was the item inserted, you'll have to search for the item again (in order to notify the adapter).
Is there a recommended way of doing it? Some tutorial I have missed? Searching around I could only find the notifyDatasetChanged() solution.
I believe what you're searching for is DiffUtil.
Here's a well explained Medium article explaining it's usage.
Another interesting answer I've come across when looking into this is the SO Answer provided by Xaver Kapeller (Just search for SortedListAdapter in the page, although his answer is a very nice read imo). His SortedListAdapter library makes the code much more simpler and cleaner.
Related
I want to create 3 level RecyclerView like tree view in kotlin. Is there any tutorial and suggestions please let me know.
I already tried so many times with ExpandableListView and 3 RecyclerView, but didn't find any proper solution.
By a multi-level RecyclerView, do you mean a RecyclerView with paths to different lists that branch depending upon which item has been selected? If that's the case, I would honestly recommend using a single adapter to cycle through multiple lists depending upon user input.
If you have a root list containing two items, each of which opens up its own list with its own unique set of data, you can easily implement code that notifies the adapter of which item in the root list was selected. From there, the adapter can update and switch the view accordingly. This can be applied to series of lists ad nauseam if you so choose, though I can't say I would recommend this kind of method for incredibly complex webs of lists that interact with each other.
Like Ircover said in their comment, I don't think a tree is necessary in this situation either, if only because (1) as stated, it isn't really best practice to do so for the kind of application you're making, and (2) it may unnecessarily over-complicate whatever you're trying to achieve with these branching paths in the first place. If you're willing/able to provide more information about what you're trying to do here, that may help others help you more precisely than I can :)
Full disclosure here: the blog post linked above is not a direct match that will solve your problem - it pertains specifically to displaying different types of data sets (from data classes and what have you,) but employs code that shows how different sets of data can be switched between in a single RecyclerView. Even if it isn't a god-sent solution or is only halfway helpful in solving your problem, I think it can provide some useful information to you.
Maybe a slightly dated question but looking into the same concept and I located this page https://blog.usejournal.com/multi-level-expandable-recycler-view-e75cf1f4ac4b .
They have made a single adapter class to take care of all the navigation and so far seems to be the least complicated example of an expandable RecyclerView, though not in kotlin.
I think I've read all the answers to all of the similar questions, and none of them seem to be fixing my problem,they're only workaround. I have recycler view with pictures taken by camera and they only update on scroll.
Using a smoothScrollToPosition() is workaround and I want to know the cause of this issue and fix it.
It's really weird because when a open my fragment and have a couple of images in the recycler view which I added earlier, deleting elements works perfect, but when I add new image from camera intent even the notification for deleting stops working, I have to do a scroll to refresh items in the adapter.
This is the part where I set the data:
viewModel.photos.observe(viewLifecycleOwner, Observer {
list->adapter.data = list
}).
Of course data is set in OnUiThread :
I checked with the debugger-- elements in list are updated.
Does anyone know the cause of this issue?
You have to tell recyclerView.adapter what exactly changed by calling notifyItemChanged. There are also other methods for inserted items, moved items, deleted items, etc. You can look at the full documentation here:
There is also another way by implementing a DiffUtil. You can research about it more. But the difference is that by using DiffUtil, you won't have to manually call those notify methods yourself.
Also, the old/unoptimized/unrecomenended way to do this is to simply call notifyDataSetChanged().
P.S. I highly think you found the somewhat the same answer while searching online and might have thought it as simply "a work around". I'm here to tell you that this is how its supposed to be handled.
Which is the name of the method/library which collapses/extends a list triggered by the user action?
Please see the image below to understand my use case.
As far I can see you have a List View with one Item, and on press you want to show a sublist. I guess you do not know Android terms and you are thinking from an abstract design point of view.
In more technical terms you need to expand a ListView when the user touches the item.
Here you can find a tutorial to use ExpandibleListVIew
Please consider that nowdays is really used in place of ListView a library called RecyclerView, and here and maybe even better this stack overflow post where you can find a valid method that explain your UX use case, without recurring to external libraries but capitalizing the method onBindViewHolder, as allegedly recommended at a Google I/O official conference.
RecyclerView offers much more functionalities, animations and should be the best option to go if the app increases in complexity, namely a real life scenario.
you can use expandable recyclerview
eg
Expandable recycler view
I've been trying to make a refreshing and auto updaing list in my app. I use Loaders to get data for that list. I saw a guide for endless ListView here and it really makes your code neat. However, when i add SwipeRefreshLayout, ProgressBarand a view indicating empty list the code becomes a total mess and is not reusable at all. I was wandering if there is a nice way to implement this often used feature.
If you want to see my code, please ask in comments (But there's nothing significant in it..)
This question might seem common to you, But I didn't find any compelling answer, So I brig it up and hope you can help.
If we have a large number of items to show in a RecyclerView, And by large I mean really large like thousands (but not at the same time), Scrolling from first item to the other items will be a real pain because of many items we have to navigate.
Possible Solution: At first look maybe breaking items to smaller parts and use of a SeekBar or a group of Buttons (like page number buttons on stackoverflow questions page) in order to choose each part(page) to review seems like a not bad idea.
Question: I'm curious is there any better and clean way to achieve this? Did android predict any tools or solution for this type of issues or it's up to developer like the solution I mentioned before?
Any advice means a lot to me and I appreciate that.
What you are looking for is called pagination. Do not query for the entire 1000 records, query for first 20 and when recyclerView is scrolled to the bottom, query for next 20. It is standard way (in list or gridview too)
You must modify your service endpoints or database query to support this.