Skip to content

Instantly share code, notes, and snippets.

@jpshelley
Created August 14, 2016 17:48
Show Gist options
  • Save jpshelley/ef6b571cde959fca9d90f10ad031ea9b to your computer and use it in GitHub Desktop.
Save jpshelley/ef6b571cde959fca9d90f10ad031ea9b to your computer and use it in GitHub Desktop.
A Sectioned Adapter for Android via Kotlin
/**
* An adapter that allows a RecyclerView to contain sections or subheaders
* much like the material docs describe.
* https://material.google.com/components/subheaders.html
*/
interface SectionedAdapter {
/**
* A list of sections to display in adapter.
*/
var sections: SparseArray<AdapterSection>
/**
* Returns true if the given position contains a section
*/
fun isSectionHeaderPosition(position: Int) = sections[position] != null
/**
* Determines the correct position based off of the number of currently displayed sections.
*/
fun sectionedPositionToPosition(sectionedPosition: Int): Int {
if (isSectionHeaderPosition(sectionedPosition)) {
return RecyclerView.NO_POSITION
}
var offset = 0
for (i in 0..sections.size() - 1) {
if (sections.valueAt(i).sectionedPosition > sectionedPosition) {
break
}
--offset
}
return sectionedPosition + offset
}
fun positionToSectionedPosition(position: Int): Int {
var offset = 0
for (i in 0..sections.size() - 1) {
if (sections.valueAt(i).firstPosition > position) {
break
}
++offset
}
return position + offset
}
/**
* Clears the current set of selections and sets a new list.
* In order for the new sections to be displayed, one must first call
* notifyDatasetChanged()
*
* @param newSections The new sections to be set
*/
fun setSections(newSections: Array<AdapterSection>) {
sections.clear()
val sortedSections = newSections.clone()
Arrays.sort<AdapterSection>(sortedSections) { o, o1 ->
when {
o.firstPosition == o1.firstPosition -> 0
o.firstPosition < o1.firstPosition -> -1
else -> 1
}
}
var offset = 0 // offset positions for the headers we're adding
sortedSections.forEach {
it.sectionedPosition = it.firstPosition + offset
sections.append(it.sectionedPosition, it)
++offset
}
}
/**
* Returns the nearest section header if one exists
*/
tailrec fun getNearestSectionHeader(sectionedPosition: Int): Int {
if (isSectionHeaderPosition(sectionedPosition)) {
return sectionedPosition
} else {
return getNearestSectionHeader(sectionedPosition - 1)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment