Declare classes for different layout / view type. I have two different layout classes: Image
and Property
, where both implement resource: Int
to store the layout id.
sealed class ViewItem(val resource: Int) { class Image(val imageResource: String): ViewItem(R.layout.content_pin_list_item_image) class Property(val icon: Int?, val value: String, val onClick: (() -> Unit)? = null, val onInit: ((viewHolder: LocalListAdapter.ViewHolder) -> Unit)? = null): ViewItem(R.layout.content_pin_list_item)}
NOTE: If you don't like sealed
class, you could use abstract
or interface
.
Declare the adapter class.
getItemViewType
return layout id, which is used inonCreateViewHolder
to inflate layout byviewType
.- I use LayoutContainer Support to enable
Android Extensions plugin supports
forViewHolder
. You can access view by id usingholder.<VIEW_ID>
syntax.
class LocalListAdapter() : RecyclerView.Adapter<LocalListAdapter.ViewHolder>() { private var items: List<ViewItem> = listOf() override fun getItemCount(): Int { return items.size } override fun getItemViewType(position: Int): Int { return items[position].resource } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context) .inflate(viewType, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = items[position] val context = holder.containerView.context when (item) { is ViewItem.Image -> { holder.apply { /* Glide.with(itemView) .load(item.imageResource) .into(imageView) imageView.setOnClickListener { } */ } } is ViewItem.Property -> { holder.apply { /* if (item.icon != null) { iconImageView.setImageResource(item.icon) } else { iconImageView.isVisible = false } textView.text = item.value if (item.onClick != null) { itemView.setOnClickListener { item.onClick?.invoke() } } else { itemView.setOnClickListener(null) itemView.setBackgroundColor(Color.TRANSPARENT) } item.onInit?.let { init -> init.invoke(this) } */ } } } } fun replaceItems(items: List<ViewItem>) { this.items = items notifyDataSetChanged() } inner class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer}
I usually initialize the adapter with empty items.
adapter = LocalListAdapter()recyclerView.adapter = adapter
When items are loaded from network or database, call replaceItems
.
val items = mutableListOf<ViewItem>()// load image items.add(ViewItem.Image("https://code.luasoftware.com/img/logo-badge.png"))// load property - infoViewItem.Property(R.drawable.ic_map_black_24dp, "My Address").also { items.add(it)}// load property - info + clickViewItem.Property(R.drawable.ic_access_time_black_24dp, "Click Me", onClick = { // do something }).also { items.add(it)}adapter.replaceItems(items)