Skip to content

Commit

Permalink
Add a List Header in RecyclerView
Browse files Browse the repository at this point in the history
  • Loading branch information
ChaMinZi committed Jun 8, 2021
1 parent 1ec3c45 commit f9fcf6c
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,27 +1,67 @@
package com.example.android.trackmysleepquality.sleeptracker

import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.android.trackmysleepquality.R
import com.example.android.trackmysleepquality.TextItemViewHolder
import com.example.android.trackmysleepquality.convertDurationToFormatted
import com.example.android.trackmysleepquality.convertNumericQualityToString
import com.example.android.trackmysleepquality.database.SleepNight
import com.example.android.trackmysleepquality.databinding.ListItemSleepNightBinding
import com.example.android.trackmysleepquality.generated.callback.OnClickListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class SleepNightAdapter(private val clickListener:SleepNightListener) : ListAdapter<SleepNight,
SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
private const val ITEM_VIEW_TYPE_HEADER = 0
private const val ITEM_VIEW_TYPE_ITEM = 1

class SleepNightAdapter(private val clickListener:SleepNightListener) : ListAdapter<DataItem,
RecyclerView.ViewHolder>(SleepNightDiffCallback()) {

private val adapterScope = CoroutineScope(Dispatchers.Default)

// ViewHolder 만 변경해서 다른 로직으로 바꿀 수 있게 캡슐화 됨
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder.from(parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when(viewType) {
ITEM_VIEW_TYPE_HEADER -> TextViewHolder.from(parent)
ITEM_VIEW_TYPE_ITEM -> ViewHolder.from(parent)
else -> throw ClassCastException("Unknown viewType $viewType")
}
}

override fun getItemViewType(position: Int): Int {
return when (getItem(position)) {
is DataItem.Header -> ITEM_VIEW_TYPE_HEADER
is DataItem.SleepNightItem -> ITEM_VIEW_TYPE_ITEM
}
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(getItem(position)!!, clickListener)
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is ViewHolder -> {
val nightItem = getItem(position) as DataItem.SleepNightItem
holder.bind(nightItem.sleepNight!!, clickListener)
}
}
}

fun addHeaderANdSubmitList(list: List<SleepNight>?) {
adapterScope.launch {
val items = when (list) {
null -> listOf(DataItem.Header)
else -> listOf(DataItem.Header) + list.map { DataItem.SleepNightItem(it) }
}
withContext(Dispatchers.Main) {
submitList(items)
}
}
}

/**
Expand Down Expand Up @@ -51,12 +91,12 @@ class SleepNightAdapter(private val clickListener:SleepNightListener) : ListAdap
*
* ListAdapter 는 new Item 과 old Item이 얼마나 변했는지 최소 개수를 알아내기 위해 사용
**/
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem.nightId == newItem.nightId
class SleepNightDiffCallback : DiffUtil.ItemCallback<DataItem>() {
override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
return oldItem == newItem
}
}
Expand All @@ -70,4 +110,27 @@ class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
**/
class SleepNightListener(val clickListener: (sleepId: Long) -> Unit) {
fun onClick(night: SleepNight) = clickListener(night.nightId)
}
}

sealed class DataItem {
data class SleepNightItem(val sleepNight: SleepNight): DataItem() {
override val id = sleepNight.nightId
}

object Header: DataItem() {
override val id = Long.MIN_VALUE
}

abstract val id: Long
}

class TextViewHolder(view: View): RecyclerView.ViewHolder(view) {
companion object {
fun from(parent: ViewGroup): TextViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.header, parent, false)
view.setBackgroundColor(Color.LTGRAY)
return TextViewHolder(view)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class SleepTrackerFragment : Fragment() {

sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.submitList(it)
adapter.addHeaderANdSubmitList(it)
}
})

Expand Down

0 comments on commit f9fcf6c

Please sign in to comment.