Android: itemdecoration in recyclerview to be text and only if a certain condition is met

1k Views Asked by At

I have a recyclerview that shows items that were bought and to be bought. The items are sorted by purchase date which can be in the past and future.

I want to add a separator between the last "past" item and the first "future" one. I know I should add a decorator like the following:

DividerItemDecoration decoration = new DividerItemDecoration(Objects.requireNonNull(getActivity()), VERTICAL);
rvItems.addItemDecoration(decoration);

The decorator is a thin horizontal line that is shown between all items. How can I make the decorator a text, something like "↓ past items ↑ future items" and to be visible only between the relevant items?

Thanks

1

There are 1 best solutions below

6
On

In such a case I think it is preferable to have a recycler view adapter that supports multiple types of items.

The separators that you call, will be sections

Example:

sealed class Item {

  data class Section(val sectionText): Item
  data class Purchases(.......): Item

}

Adapter:

class MyAdapter(private val items: List<Item>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

  companion object {
    const val TYPE_PURCHASES = 0
    const val TYPE_SECTION = 1
  }

  override fun getItemViewType(position: Int): Int {
    val type = when (items[position]) {
      is Items.Section -> TYPE_SECTION
      // other types...
      else -> TYPE_PURCHASES
    }
    return type
  }

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    val viewHolder: RecyclerView.ViewHolder = when (viewType) {
      TYPE_PURCHASES -> {}
      // other view holders...
      else -> {}
    }
    return viewHolder
  }

  override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
     when(holder) {
        is SectionViewHolder -> bindSectionViewHolder(holder)
        is PurchasesViewHolder -> bindSectionViewHolder(holder)
     }
  }

  override fun getItemCount() = items.size
}

Then create the corresponding ViewHolders for each type and instantiate them at onCreateViewHolder.

And when you pass the list of Items in the adapter you should have logic that adds either a Section or an Item to the list.

Similar example from one of my projects:

        .subscribeBy(onSuccess = {
            val list = mutableListOf<IViewModel>()
            val previousBookingDate = Calendar.getInstance()
            val bookingDate = Calendar.getInstance()
            it.data?.fold(Date(0)) { previousHeader, bookable ->
                previousBookingDate.time = previousHeader
                bookingDate.time = bookable.getStartDate()
                val timeIgnoringComparator = DateUtils.TimeIgnoringComparator()
                if (timeIgnoringComparator.compare(previousBookingDate, bookingDate) != 0) {
                    list.add(SectionViewModel(bookable.getStartDate(), isDefaultSearch || isDefaultCenterSelected()))
                }
                list.add(BookableItemViewModel(bookable))

                bookable.getStartDate()
            }

            searchResultsLiveData.value = list
        }, onError = {
            isError.setValue(Event(Pair(null, Runnable { performSearch() })))
        })

I suggest taking a look at this library to quickly make lists with different item types.