diff options
| -rw-r--r-- | android/src/main/kotlin/net/mullvad/mullvadvpn/util/AdapterWithHeader.kt | 110 | ||||
| -rw-r--r-- | android/src/main/kotlin/net/mullvad/mullvadvpn/util/HeaderOrHolder.kt | 9 |
2 files changed, 119 insertions, 0 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/util/AdapterWithHeader.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/util/AdapterWithHeader.kt new file mode 100644 index 0000000000..0cddaaa123 --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/util/AdapterWithHeader.kt @@ -0,0 +1,110 @@ +package net.mullvad.mullvadvpn.util + +import android.support.v7.widget.RecyclerView.Adapter +import android.support.v7.widget.RecyclerView.AdapterDataObserver +import android.support.v7.widget.RecyclerView.ViewHolder +import android.view.LayoutInflater +import android.view.ViewGroup + +class AdapterWithHeader<H : ViewHolder>( + val adapter: Adapter<H>, + val headerLayoutId: Int +) : Adapter<HeaderOrHolder<H>>() { + private val observer = object : AdapterDataObserver() { + override fun onChanged() { + notifyDataSetChanged() + } + + override fun onItemRangeChanged(start: Int, count: Int) { + notifyItemRangeChanged(start + 1, count) + } + + override fun onItemRangeChanged(start: Int, count: Int, payload: Any?) { + notifyItemRangeChanged(start + 1, count, payload) + } + + override fun onItemRangeInserted(start: Int, count: Int) { + notifyItemRangeInserted(start + 1, count) + } + + override fun onItemRangeMoved(from: Int, to: Int, count: Int) { + if (from == to) { + notifyItemRangeChanged(from + 1, count) + } else { + val sourceStart = from + 1 + val sourceEnd = sourceStart + count + val destinationStart = to + 1 + val destinationEnd = destinationStart + count + + val ascendingIndices = + (sourceStart..sourceEnd).zip(destinationStart..destinationEnd) + + val indices = if (from < to) { + ascendingIndices.asReversed() + } else { + ascendingIndices + } + + for ((source, destination) in indices) { + notifyItemMoved(source, destination) + } + } + } + + override fun onItemRangeRemoved(start: Int, count: Int) { + notifyItemRangeRemoved(start + 1, count) + } + } + + init { + adapter.registerAdapterDataObserver(observer) + } + + override fun getItemCount() = adapter.itemCount + 1 + + override fun getItemId(position: Int): Long { + if (position == 0) { + return 0L + } else { + return adapter.getItemId(position - 1) + 1 + } + } + + override fun getItemViewType(position: Int): Int { + if (position == 0) { + return 0 + } else { + return adapter.getItemViewType(position - 1) + 1 + } + } + + override fun onBindViewHolder(holder: HeaderOrHolder<H>, position: Int) { + when (holder) { + is HeaderOrHolder.Header -> { + if (position != 0) { + throw IllegalArgumentException("Adapter position is not for the header") + } + } + is HeaderOrHolder.Holder -> { + if (position > 0) { + adapter.onBindViewHolder(holder.holder, position - 1) + } else { + throw IllegalArgumentException("Adapter position is for the header") + } + } + } + } + + override fun onCreateViewHolder(parentView: ViewGroup, viewType: Int): HeaderOrHolder<H> { + if (viewType == 0) { + val inflater = LayoutInflater.from(parentView.context) + val view = inflater.inflate(headerLayoutId, parentView, false) + + return HeaderOrHolder.Header(view) + } else { + val holder = adapter.onCreateViewHolder(parentView, viewType - 1) + + return HeaderOrHolder.Holder(holder) + } + } +} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/util/HeaderOrHolder.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/util/HeaderOrHolder.kt new file mode 100644 index 0000000000..631d69100e --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/util/HeaderOrHolder.kt @@ -0,0 +1,9 @@ +package net.mullvad.mullvadvpn.util + +import android.support.v7.widget.RecyclerView.ViewHolder +import android.view.View + +sealed class HeaderOrHolder<H : ViewHolder>(itemView: View) : ViewHolder(itemView) { + class Header<H : ViewHolder>(headerView: View) : HeaderOrHolder<H>(headerView) + class Holder<H : ViewHolder>(val holder: H) : HeaderOrHolder<H>(holder.itemView) +} |
