Skip to content

Instantly share code, notes, and snippets.

@ppamorim
Last active July 28, 2020 02:47
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ppamorim/1f18448c1441716f8ab15b9ad2e8874e to your computer and use it in GitHub Desktop.
Save ppamorim/1f18448c1441716f8ab15b9ad2e8874e to your computer and use it in GitHub Desktop.
val audioRecordAdapter = ItemAdapter(data)
val sections = mutableListOf<Section>()
sections.add(DateSection(0, "Today"))
sections.add(DateSection(2, "15/05/2016"))
val customSectionAdapter = CustomSectionAdapter()
customSectionAdapter.configSections(sections)
val sectionAdapter = SectionedRecyclerViewAdapter(customSectionAdapter, audioRecordAdapter)
recyclerView.adapter = sectionAdapter
/**
* Base class that represents the position
* of the Section on the RecyclerView.
*/
open class Section(val firstPosition: Int, var sectionedPosition: Int = 0)
/**
* This class represents the base implementation
* of the section. To use this you need to extends
* your class and inflate and bind your data like
* a {@link #RecyclerView.Adapter}.
*/
abstract class SectionAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var sections : SparseArray<Section> = SparseArray()
override fun getItemCount() = sections.size()
fun configSections(sections: List<Section>) {
this.sections.clear()
sections.sortedWith(Comparator { lhs, rhs ->
if (lhs.firstPosition == rhs.firstPosition) 0
else if (lhs.firstPosition < rhs.firstPosition) -1
else 1
})
var offset = 0
sections.forEach {
it.sectionedPosition = it.firstPosition + offset
this.sections.append(it.sectionedPosition, it)
++offset
}
}
}
package com.tpro.ui.helper.sectionRecyclerView
import android.support.v7.widget.RecyclerView
import android.view.ViewGroup
import com.tpro.ui.adapter.viewType.SectionedType
class SectionedRecyclerViewAdapter(
val sectionAdapter: SectionAdapter,
val itemAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>):
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var valid = true
init {
itemAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
toggleValid()
notifyDataSetChanged()
}
override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
toggleValid()
notifyItemRangeChanged(positionStart, itemCount)
}
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
toggleValid()
notifyItemRangeInserted(positionStart, itemCount)
}
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
toggleValid()
notifyItemRangeRemoved(positionStart, itemCount)
}
})
}
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder? {
return when(viewType) {
SectionedType.HEADER.value -> sectionAdapter.onCreateViewHolder(parent, viewType)
else -> itemAdapter.onCreateViewHolder(parent, viewType - 1)
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
if (isSectionHeaderPosition(position)) {
sectionAdapter.onBindViewHolder(holder, position)
} else {
itemAdapter.onBindViewHolder(holder, sectionedPositionToPosition(position))
}
}
override fun getItemViewType(position: Int) =
if (isSectionHeaderPosition(position))
SectionedType.HEADER.value
else itemAdapter.getItemViewType(sectionedPositionToPosition(position)) + 1
override fun getItemId(position: Int) =
if(isSectionHeaderPosition(position))
(Integer.MAX_VALUE - sectionAdapter.sections.indexOfKey(position)).toLong() else
itemAdapter.getItemId(sectionedPositionToPosition(position))
override fun getItemCount() = if(valid) itemAdapter.itemCount + sectionAdapter.itemCount else 0
fun toggleValid() = itemAdapter.itemCount > 0
fun positionToSectionedPosition(position: Int): Int {
var offset = 0
for (i in 0..sectionAdapter.sections.size() - 1) {
if (sectionAdapter.sections.valueAt(i).sectionedPosition > position) {
break
}
++offset
}
return position + offset
}
fun sectionedPositionToPosition(sectionedPosition: Int): Int {
if (isSectionHeaderPosition(sectionedPosition)) {
return RecyclerView.NO_POSITION
}
var offset = 0
for (i in 0..sectionAdapter.sections.size() - 1) {
if (sectionAdapter.sections.valueAt(i).sectionedPosition > sectionedPosition) {
break
}
--offset
}
return sectionedPosition + offset
}
fun isSectionHeaderPosition(position: Int)= sectionAdapter.sections.get(position) != null
}
/**
* Type of item on RecyclerView. Used
* by the adapter.
*/
enum class SectionedType(val value: Int) { HEADER(0), ITEM(1) }
Are you using ProGuard? Use this:
The files above are localized inside the folder `com.myProject.ui.helper`,
then you need to do something similar of this:
-dontwarn com.myProject.ui.helper.sectionRecyclerView.**
-keep class com.myProject.ui.helper.sectionRecyclerView.** { *; }
-keep interface com.myProject.ui.helper.sectionRecyclerView.** { *; }
@Sarim-Ahmed93
Copy link

Where is ItemAdapter(data) class?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment