Last active
October 18, 2023 00:16
-
-
Save NickHolcombe/0e1c27892d6b73271f10e12268f40187 to your computer and use it in GitHub Desktop.
Example of a RecyclerView Adapter based on ListAdapter with a header
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example | |
import android.support.v7.recyclerview.extensions.AsyncDifferConfig | |
import android.support.v7.recyclerview.extensions.AsyncListDiffer | |
import android.support.v7.util.DiffUtil | |
import android.support.v7.util.ListUpdateCallback | |
import android.support.v7.widget.RecyclerView | |
/** | |
* {@link RecyclerView.Adapter RecyclerView.Adapter} base class based on | |
* {@link ListAdapter} for presenting List data with header rows in a | |
* {@link RecyclerView}, including computing diffs between Lists on a background thread. | |
* | |
* @param <T> Type of the Lists this Adapter will receive. | |
* @param <VH> A class that extends ViewHolder that will be used by the adapter. | |
* @param diffCallback DiffUtil.ItemCallback<T> class used by DiffUtils for comparing <T> items | |
* @param headerOffset Int number of header rows before list | |
*/ | |
abstract class ListAdapterWithHeader<T, VH : RecyclerView.ViewHolder>( | |
private val diffCallback: DiffUtil.ItemCallback<T>, | |
private val headerOffset: Int = 1 | |
) : RecyclerView.Adapter<VH>() { | |
private val mHelper by lazy { | |
AsyncListDiffer<T>( | |
OffsetListUpdateCallback(this, headerOffset), | |
AsyncDifferConfig.Builder<T>(diffCallback).build() | |
) | |
} | |
/** | |
* Submits a new list to be diffed, and displayed. | |
* | |
* If a list is already being displayed, a diff will be computed on a background thread, which | |
* will dispatch Adapter.notifyItem events on the main thread. | |
* | |
* @param list The new list to be displayed. | |
*/ | |
fun submitList(list: List<T>?) { | |
mHelper.submitList(list) | |
} | |
/** | |
* Accounts for header offset | |
*/ | |
fun getItem(position: Int): T { | |
return mHelper.currentList[position - headerOffset] | |
} | |
/** | |
* Returns the total number of items in the data set held by the adapter (includes header offset) | |
* | |
* @return The total number of items in this adapter (plus the header offset) | |
*/ | |
override fun getItemCount(): Int { | |
return mHelper.currentList.size + headerOffset | |
} | |
/** | |
* ListUpdateCallback that dispatches update events to the given adapter with a position offset to | |
* allow for the number of header items. | |
* | |
* @see DiffUtil.DiffResult#dispatchUpdatesTo(RecyclerView.Adapter) | |
*/ | |
private class OffsetListUpdateCallback( | |
private val adapter: RecyclerView.Adapter<*>, | |
private val offset: Int | |
) : ListUpdateCallback { | |
fun offsetPosition(originalPosition: Int): Int { | |
return originalPosition + offset | |
} | |
override fun onInserted(position: Int, count: Int) { | |
adapter.notifyItemRangeInserted(offsetPosition(position), count) | |
} | |
override fun onRemoved(position: Int, count: Int) { | |
adapter.notifyItemRangeRemoved(offsetPosition(position), count) | |
} | |
override fun onMoved(fromPosition: Int, toPosition: Int) { | |
adapter.notifyItemMoved(offsetPosition(fromPosition), offsetPosition(toPosition)) | |
} | |
override fun onChanged(position: Int, count: Int, payload: Any?) { | |
adapter.notifyItemRangeChanged(offsetPosition(position), count, payload) | |
} | |
} | |
} |
Thank you
Thanks for this!
Great
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi NickHolcombe, I converted your adapter to Java and put it https://gist.github.com/aubryll/f70b81bfa5ff86cdb4efd86148d60163 all thanks to you, I was almost loosing my mind looking for a solution to add a header to my pagedlistadapter.