Skip to content

Commit

Permalink
Issues boostcampwm-2022#287 feat: Setting RecyclerView 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
audxo112 committed Feb 28, 2023
1 parent 24a4fc2 commit ddef227
Show file tree
Hide file tree
Showing 15 changed files with 310 additions and 346 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.lighthouse.core.android.utils.permission.StoragePermissionManager
import com.lighthouse.core.android.utils.permission.core.permissions
import com.lighthouse.features.common.binding.viewBindings
Expand All @@ -28,12 +30,12 @@ class MainContainerFragment : Fragment(R.layout.fragment_main_container) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

// setUpBottomNavigation()
setUpBottomNavigation()
}

private fun setUpBottomNavigation() {
// val navHostFragment = childFragmentManager.findFragmentById(R.id.fcv_main) as NavHostFragment
// val navController = navHostFragment.navController
// binding.bnv.setupWithNavController(navController)
val navHostFragment = childFragmentManager.findFragmentById(R.id.fcv_main) as NavHostFragment
val navController = navHostFragment.navController
binding.bnv.setupWithNavController(navController)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:defaultNavHost="false"
app:navGraph="@navigation/main_container_nav_graph"
app:layout_constraintBottom_toTopOf="@id/bnv"
app:layout_constraintEnd_toEndOf="parent"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.lighthouse.features.setting.adapter

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.lighthouse.features.setting.R
import com.lighthouse.features.setting.databinding.ItemButtonBinding
import com.lighthouse.features.setting.model.SettingItem
import com.lighthouse.features.setting.model.SettingMenu

internal class ButtonViewHolder(
parent: ViewGroup,
private val onClick: (SettingMenu) -> Unit,
private val binding: ItemButtonBinding = ItemButtonBinding.bind(
LayoutInflater.from(parent.context).inflate(R.layout.item_button, parent, false)
)
) : RecyclerView.ViewHolder(binding.root) {

fun bind(item: SettingItem.Button) {
val context = binding.root.context
binding.tvLabel.text = item.menu.uiText.asString(context)
binding.root.setOnClickListener {
onClick(item.menu)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.lighthouse.features.setting.adapter

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.lighthouse.features.setting.R
import com.lighthouse.features.setting.databinding.ItemDividerBinding

internal class DividerViewHolder(
parent: ViewGroup,
binding: ItemDividerBinding = ItemDividerBinding.bind(
LayoutInflater.from(parent.context).inflate(R.layout.item_divider, parent, false)
)
) : RecyclerView.ViewHolder(binding.root)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.lighthouse.features.setting.adapter

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.lighthouse.features.setting.R
import com.lighthouse.features.setting.databinding.ItemGroupHeaderBinding
import com.lighthouse.features.setting.model.SettingItem

internal class GroupHeaderViewHolder(
parent: ViewGroup,
private val binding: ItemGroupHeaderBinding = ItemGroupHeaderBinding.bind(
LayoutInflater.from(parent.context).inflate(R.layout.item_group_header, parent, false)
)
) : RecyclerView.ViewHolder(binding.root) {

fun bind(item: SettingItem.GroupHeader) {
val context = binding.root.context
binding.tvHeaderLabel.text = item.uiText.asString(context)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.lighthouse.features.setting.adapter

import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.lighthouse.features.setting.model.SettingItem
import com.lighthouse.features.setting.model.SettingMenu

internal class SettingAdapter(
private val onClick: (SettingMenu) -> Unit,
private val onCheckedChange: (SettingMenu, Boolean) -> Unit
) : ListAdapter<SettingItem, RecyclerView.ViewHolder>(SettingItemDiff()) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
TYPE_GROUP_HEADER -> GroupHeaderViewHolder(parent)
TYPE_DIVIDER -> DividerViewHolder(parent)
TYPE_BUTTON -> ButtonViewHolder(parent, onClick)
TYPE_STATE_BUTTON -> StateButtonViewHolder(parent, onClick)
TYPE_STATE_SWITCH -> StateSwitchViewHolder(parent, onCheckedChange)
else -> throw IllegalArgumentException("잘못된 viewType 입니다.")
}
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = getItem(position)
when {
holder is GroupHeaderViewHolder && item is SettingItem.GroupHeader -> holder.bind(item)
holder is ButtonViewHolder && item is SettingItem.Button -> holder.bind(item)
holder is StateButtonViewHolder && item is SettingItem.StateButton -> holder.bind(item)
holder is StateSwitchViewHolder && item is SettingItem.StateSwitch -> holder.bind(item)
}
}

override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList<Any>
) {
if (payloads.isNotEmpty()) {
val flag = payloads.getOrNull(0) as? Int ?: 0
val item = getItem(position)
when {
holder is StateButtonViewHolder && item is SettingItem.StateButton &&
flag and SettingItemDiff.UPDATE_STATE == SettingItemDiff.UPDATE_STATE -> {
holder.bindState(item)
}

holder is StateSwitchViewHolder && item is SettingItem.StateSwitch &&
flag and SettingItemDiff.UPDATE_STATE == SettingItemDiff.UPDATE_STATE -> {
holder.bindState(item)
}
}
} else {
onBindViewHolder(holder, position)
}
}

override fun getItemViewType(position: Int): Int {
return when (getItem(position)) {
is SettingItem.GroupHeader -> TYPE_GROUP_HEADER
is SettingItem.Divider -> TYPE_DIVIDER
is SettingItem.Button -> TYPE_BUTTON
is SettingItem.StateButton -> TYPE_STATE_BUTTON
is SettingItem.StateSwitch -> TYPE_STATE_SWITCH
}
}

companion object {
private const val TYPE_GROUP_HEADER = 1
private const val TYPE_DIVIDER = 2
private const val TYPE_BUTTON = 3
private const val TYPE_STATE_BUTTON = 4
private const val TYPE_STATE_SWITCH = 5
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.lighthouse.features.setting.adapter

import androidx.recyclerview.widget.DiffUtil
import com.lighthouse.features.setting.model.SettingItem

internal class SettingItemDiff : DiffUtil.ItemCallback<SettingItem>() {

override fun areItemsTheSame(oldItem: SettingItem, newItem: SettingItem): Boolean {
return oldItem === newItem
}

override fun areContentsTheSame(oldItem: SettingItem, newItem: SettingItem): Boolean {
return oldItem == newItem
}

override fun getChangePayload(oldItem: SettingItem, newItem: SettingItem): Any? {
if (oldItem is SettingItem.StateButton &&
newItem is SettingItem.StateButton &&
oldItem.state != newItem.state
) {
return UPDATE_STATE
} else if (
oldItem is SettingItem.StateSwitch &&
newItem is SettingItem.StateSwitch &&
oldItem.state != newItem.state
) {
return UPDATE_STATE
}
return null
}

companion object {
const val UPDATE_STATE = 1 shl 0
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.lighthouse.features.setting.adapter

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.lighthouse.features.setting.R
import com.lighthouse.features.setting.databinding.ItemStateButtonBinding
import com.lighthouse.features.setting.model.SettingItem
import com.lighthouse.features.setting.model.SettingMenu

internal class StateButtonViewHolder(
parent: ViewGroup,
private val onClick: (SettingMenu) -> Unit,
private val binding: ItemStateButtonBinding = ItemStateButtonBinding.bind(
LayoutInflater.from(parent.context).inflate(R.layout.item_state_button, parent, false)
)
) : RecyclerView.ViewHolder(binding.root) {

fun bind(item: SettingItem.StateButton) {
val context = binding.root.context
binding.tvLabel.text = item.menu.uiText.asString(context)
setUpState(item)
binding.root.setOnClickListener {
onClick(item.menu)
}
}

fun bindState(item: SettingItem.StateButton) {
setUpState(item)
}

private fun setUpState(item: SettingItem.StateButton) {
val context = binding.root.context
binding.tvState.text = item.state.asString(context)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.lighthouse.features.setting.adapter

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.lighthouse.features.setting.R
import com.lighthouse.features.setting.databinding.ItemStateSwitchBinding
import com.lighthouse.features.setting.model.SettingItem
import com.lighthouse.features.setting.model.SettingMenu

internal class StateSwitchViewHolder(
parent: ViewGroup,
private val onCheckedChange: (SettingMenu, Boolean) -> Unit,
private val binding: ItemStateSwitchBinding = ItemStateSwitchBinding.bind(
LayoutInflater.from(parent.context).inflate(R.layout.item_state_switch, parent, false)
)
) : RecyclerView.ViewHolder(binding.root) {

fun bind(item: SettingItem.StateSwitch) {
val context = binding.root.context
binding.tvLabel.text = item.menu.uiText.asString(context)
setUpState(item)
}

fun bindState(item: SettingItem.StateSwitch) {
setUpState(item)
}

private fun setUpState(item: SettingItem.StateSwitch) {
binding.smState.apply {
setOnCheckedChangeListener(null)
isChecked = item.state
setOnCheckedChangeListener { _, isChecked ->
onCheckedChange(item.menu, isChecked)
}
}
}
}
Loading

0 comments on commit ddef227

Please sign in to comment.