Created
August 14, 2016 17:48
-
-
Save jpshelley/ef6b571cde959fca9d90f10ad031ea9b to your computer and use it in GitHub Desktop.
A Sectioned Adapter for Android via Kotlin
This file contains hidden or 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
/** | |
* 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