Skip to content

Instantly share code, notes, and snippets.

@maxlord
Created November 22, 2017 12:20
Show Gist options
  • Save maxlord/30634441bef7a356ad4f562ab71388be to your computer and use it in GitHub Desktop.
Save maxlord/30634441bef7a356ad4f562ab71388be to your computer and use it in GitHub Desktop.
ListAdapter with paging support
class CarNewsAdapter(
private val context: Context,
private val dateTimeFormatter: DateTimeFormatter,
private val recycler: RecyclerView,
private val callback: Callback,
private val onLoadMoreListener: OnLoadMoreListener) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val imageRoundedTransformation = RoundedCornersTransformation(context, 8, 0)
private var isLoading = false
private var visibleThreshold = THRESHOLD_LIMIT
private var lastVisibleItem = 0
private var totalItemCount = 0
private var layoutManager = recycler.layoutManager as LinearLayoutManager
private var scrollListener: RecyclerView.OnScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
totalItemCount = layoutManager.itemCount
lastVisibleItem = layoutManager.findLastVisibleItemPosition()
if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
onLoadMoreListener.onLoadMore()
isLoading = true
}
}
}
init {
recycler.addOnScrollListener(scrollListener)
}
interface Callback {
fun onItemClick(item: CarNewsViewItem)
}
class ItemViewHolder(view: View, adapter: CarNewsAdapter) : RecyclerView.ViewHolder(view) {
init {
view.setOnClickListener {
adapter.callback.onItemClick(it?.tag as CarNewsViewItem)
}
}
}
class ProgressViewHolder(view: View) : RecyclerView.ViewHolder(view)
private val items: MutableList<CarNewsViewItem?> = arrayListOf()
fun clear() {
items.clear()
}
fun addItems(items: List<CarNewsViewItem?>) {
val ind = itemCount
if (ind > 0) {
removeItem(ind - 1)
notifyItemRemoved(ind - 1)
}
if (items.isNotEmpty()) {
this.items.addAll(items)
notifyItemRangeInserted(itemCount, items.size)
addProgressItem()
notifyItemInserted(itemCount)
} else {
recycler.removeOnScrollListener(scrollListener)
}
setLoaded()
}
fun addProgressItem() {
this.items.add(null)
}
fun getItem(position: Int): CarNewsViewItem? {
if (position < items.size) {
return items[position]
}
return null
}
fun removeItem(position: Int) {
if (position < items.size) {
items.removeAt(position)
}
}
private fun setLoaded() {
isLoading = false
}
override fun getItemViewType(position: Int): Int {
return if (items[position] != null) VIEW_TYPE_ITEM else VIEW_TYPE_LOADING
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder? {
if (viewType == VIEW_TYPE_ITEM) {
val view = LayoutInflater.from(context).inflate(R.layout.list_item_car_news, parent, false)
return ItemViewHolder(view, this)
} else if (viewType == VIEW_TYPE_LOADING) {
val view = LayoutInflater.from(context).inflate(R.layout.list_item_progress, parent, false)
return ProgressViewHolder(view)
}
return null
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is ItemViewHolder -> {
val item = items[position]
with(holder.itemView) {
item?.let {
tag = it
title.text = it.title
date.text = dateTimeFormatter.formatDate(it.date)
Glide.with(context)
.load(it.image)
.fitCenter()
.centerCrop()
.bitmapTransform(imageRoundedTransformation)
.into(image)
}
}
}
is ProgressViewHolder -> {
holder.itemView.progress.isIndeterminate = true
}
}
}
override fun getItemCount(): Int {
return items.size
}
}
private const val VIEW_TYPE_ITEM = 0
private const val VIEW_TYPE_LOADING = 1
private const val THRESHOLD_LIMIT = 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment