From ddef227c1f31ed9be401519c902ca14c85453be1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AA=85=EC=84=9D?= Date: Tue, 28 Feb 2023 23:07:39 +0900 Subject: [PATCH] =?UTF-8?q?Issues=20#287=20feat:=20Setting=20RecyclerView?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/main/ui/MainContainerFragment.kt | 10 +- .../res/layout/fragment_main_container.xml | 2 +- .../setting/adapter/ButtonViewHolder.kt | 26 ++ .../setting/adapter/DividerViewHolder.kt | 14 + .../setting/adapter/GroupHeaderViewHolder.kt | 21 ++ .../setting/adapter/SettingAdapter.kt | 76 ++++ .../setting/adapter/SettingItemDiff.kt | 35 ++ .../setting/adapter/StateButtonViewHolder.kt | 36 ++ .../setting/adapter/StateSwitchViewHolder.kt | 38 ++ .../src/main/res/layout/fragment_setting.xml | 325 +----------------- .../src/main/res/layout/item_button.xml | 9 +- .../src/main/res/layout/item_divider.xml | 8 +- .../src/main/res/layout/item_group_header.xml | 10 +- .../src/main/res/layout/item_state_button.xml | 24 +- .../src/main/res/layout/item_state_switch.xml | 22 +- 15 files changed, 310 insertions(+), 346 deletions(-) create mode 100644 features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/ButtonViewHolder.kt create mode 100644 features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/DividerViewHolder.kt create mode 100644 features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/GroupHeaderViewHolder.kt create mode 100644 features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/SettingAdapter.kt create mode 100644 features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/SettingItemDiff.kt create mode 100644 features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/StateButtonViewHolder.kt create mode 100644 features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/StateSwitchViewHolder.kt diff --git a/features/ui-main/src/main/java/com/lighthouse/features/main/ui/MainContainerFragment.kt b/features/ui-main/src/main/java/com/lighthouse/features/main/ui/MainContainerFragment.kt index 9cecb61c5..49013c0d0 100644 --- a/features/ui-main/src/main/java/com/lighthouse/features/main/ui/MainContainerFragment.kt +++ b/features/ui-main/src/main/java/com/lighthouse/features/main/ui/MainContainerFragment.kt @@ -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 @@ -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) } } diff --git a/features/ui-main/src/main/res/layout/fragment_main_container.xml b/features/ui-main/src/main/res/layout/fragment_main_container.xml index 767c540c7..5216aec2e 100644 --- a/features/ui-main/src/main/res/layout/fragment_main_container.xml +++ b/features/ui-main/src/main/res/layout/fragment_main_container.xml @@ -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" diff --git a/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/ButtonViewHolder.kt b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/ButtonViewHolder.kt new file mode 100644 index 000000000..2818319c0 --- /dev/null +++ b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/ButtonViewHolder.kt @@ -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) + } + } +} diff --git a/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/DividerViewHolder.kt b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/DividerViewHolder.kt new file mode 100644 index 000000000..9922e92d8 --- /dev/null +++ b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/DividerViewHolder.kt @@ -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) diff --git a/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/GroupHeaderViewHolder.kt b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/GroupHeaderViewHolder.kt new file mode 100644 index 000000000..489be8f3a --- /dev/null +++ b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/GroupHeaderViewHolder.kt @@ -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) + } +} diff --git a/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/SettingAdapter.kt b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/SettingAdapter.kt new file mode 100644 index 000000000..959e66608 --- /dev/null +++ b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/SettingAdapter.kt @@ -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(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 + ) { + 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 + } +} diff --git a/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/SettingItemDiff.kt b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/SettingItemDiff.kt new file mode 100644 index 000000000..3c0d2e226 --- /dev/null +++ b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/SettingItemDiff.kt @@ -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() { + + 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 + } +} diff --git a/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/StateButtonViewHolder.kt b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/StateButtonViewHolder.kt new file mode 100644 index 000000000..b843ab274 --- /dev/null +++ b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/StateButtonViewHolder.kt @@ -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) + } +} diff --git a/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/StateSwitchViewHolder.kt b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/StateSwitchViewHolder.kt new file mode 100644 index 000000000..3324ba286 --- /dev/null +++ b/features/ui-setting/src/main/java/com/lighthouse/features/setting/adapter/StateSwitchViewHolder.kt @@ -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) + } + } + } +} diff --git a/features/ui-setting/src/main/res/layout/fragment_setting.xml b/features/ui-setting/src/main/res/layout/fragment_setting.xml index c0470e0f6..7d39f5588 100644 --- a/features/ui-setting/src/main/res/layout/fragment_setting.xml +++ b/features/ui-setting/src/main/res/layout/fragment_setting.xml @@ -48,329 +48,6 @@ android:id="@+id/rv_list" android:layout_width="match_parent" android:layout_height="match_parent" - app:layout_behavior="@string/appbar_scrolling_view_behavior"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> \ No newline at end of file diff --git a/features/ui-setting/src/main/res/layout/item_button.xml b/features/ui-setting/src/main/res/layout/item_button.xml index 78e83e1c4..35f5d7227 100644 --- a/features/ui-setting/src/main/res/layout/item_button.xml +++ b/features/ui-setting/src/main/res/layout/item_button.xml @@ -1,9 +1,10 @@ - - - + android:layout_height="wrap_content" + android:paddingVertical="16dp"/> \ No newline at end of file diff --git a/features/ui-setting/src/main/res/layout/item_divider.xml b/features/ui-setting/src/main/res/layout/item_divider.xml index 78e83e1c4..00c78f7aa 100644 --- a/features/ui-setting/src/main/res/layout/item_divider.xml +++ b/features/ui-setting/src/main/res/layout/item_divider.xml @@ -1,9 +1,7 @@ - - - + \ No newline at end of file diff --git a/features/ui-setting/src/main/res/layout/item_group_header.xml b/features/ui-setting/src/main/res/layout/item_group_header.xml index 78e83e1c4..83dcd7b89 100644 --- a/features/ui-setting/src/main/res/layout/item_group_header.xml +++ b/features/ui-setting/src/main/res/layout/item_group_header.xml @@ -1,9 +1,11 @@ - - - + android:layout_height="wrap_content" + android:background="@drawable/bg_on_surface_12" + android:paddingVertical="8dp"/> \ No newline at end of file diff --git a/features/ui-setting/src/main/res/layout/item_state_button.xml b/features/ui-setting/src/main/res/layout/item_state_button.xml index 78e83e1c4..09d99aad2 100644 --- a/features/ui-setting/src/main/res/layout/item_state_button.xml +++ b/features/ui-setting/src/main/res/layout/item_state_button.xml @@ -1,9 +1,29 @@ - + + android:layout_height="wrap_content"> + + + + \ No newline at end of file diff --git a/features/ui-setting/src/main/res/layout/item_state_switch.xml b/features/ui-setting/src/main/res/layout/item_state_switch.xml index 1d13f9b0e..950c0960e 100644 --- a/features/ui-setting/src/main/res/layout/item_state_switch.xml +++ b/features/ui-setting/src/main/res/layout/item_state_switch.xml @@ -1,9 +1,27 @@ - + + android:layout_height="wrap_content"> + + +