diff --git a/app/src/main/java/com/umc/coumo/domain/model/MenuModel.kt b/app/src/main/java/com/umc/coumo/domain/model/MenuModel.kt new file mode 100644 index 0000000..8051a66 --- /dev/null +++ b/app/src/main/java/com/umc/coumo/domain/model/MenuModel.kt @@ -0,0 +1,11 @@ +package com.umc.coumo.domain.model + +import android.net.Uri + +data class MenuModel( + val id: Int, + val name: String, + val content: String, + val image: Uri? = null, + val isNew: Boolean = false +) \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/domain/type/DetailTabType.kt b/app/src/main/java/com/umc/coumo/domain/type/DetailTabType.kt new file mode 100644 index 0000000..c9f4a93 --- /dev/null +++ b/app/src/main/java/com/umc/coumo/domain/type/DetailTabType.kt @@ -0,0 +1,6 @@ +package com.umc.coumo.domain.type + +enum class DetailTabType { + INFO, + COUPON, +} \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/domain/viewmodel/HomeViewModel.kt b/app/src/main/java/com/umc/coumo/domain/viewmodel/HomeViewModel.kt new file mode 100644 index 0000000..3d65db3 --- /dev/null +++ b/app/src/main/java/com/umc/coumo/domain/viewmodel/HomeViewModel.kt @@ -0,0 +1,38 @@ +package com.umc.coumo.domain.viewmodel + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.umc.coumo.domain.model.MenuModel +import com.umc.coumo.domain.type.DetailTabType +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class HomeViewModel @Inject constructor(): ViewModel() { + + private val _currentTab = MutableLiveData(DetailTabType.INFO) + val currentTab: LiveData get() = _currentTab + + private val _menuList = MutableLiveData>() + val menuList: LiveData> get() = _menuList + + init { + testData() + } + + fun changeTab(tab: DetailTabType) { + _currentTab.value = tab + } + + private fun testData() { + val list = listOf( + MenuModel(id = 0, name = "아이스 바닐라 라떼", content = "Tall: 4,800\nGrande: 6,800\nTrenta: 6,800"), + MenuModel(id = 1, name = "아이스 바닐라 라떼2", content = "Tall: 4,800\nGrande: 6,800\nTrenta: 6,800", isNew = true), + MenuModel(id = 2, name = "아이스 바닐라 라떼3", content = "Tall: 4,800\nGrande: 6,800\nTrenta: 6,800",), + MenuModel(id = 3, name = "아이스 바닐라 라떼4", content = "Tall: 4,800\nGrande: 6,800\nTrenta: 6,800",), + MenuModel(id = 4, name = "아이스 바닐라 라떼5", content = "Tall: 4,800\nGrande: 6,800\nTrenta: 6,800",), + ) + _menuList.value = list + } +} \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/presentation/activity/MainActivity.kt b/app/src/main/java/com/umc/coumo/presentation/activity/MainActivity.kt index c572cf4..9895b1b 100644 --- a/app/src/main/java/com/umc/coumo/presentation/activity/MainActivity.kt +++ b/app/src/main/java/com/umc/coumo/presentation/activity/MainActivity.kt @@ -1,10 +1,7 @@ package com.umc.coumo.presentation.activity -import androidx.appcompat.app.AppCompatActivity import android.os.Bundle -import android.util.Log import androidx.activity.viewModels -import androidx.lifecycle.lifecycleScope import com.umc.coumo.R import com.umc.coumo.databinding.ActivityMainBinding import com.umc.coumo.domain.type.TabType @@ -29,6 +26,14 @@ class MainActivity : BindingActivity(R.layout.activity_main binding.viewpager.isUserInputEnabled = false //스와이프 방지 setNaviButton() + setObserver() + } + + private fun setObserver () { + viewModel.currentPageIndex.observe(this) { + if (it == TabType.COUPON) + binding.viewpager.setCurrentItem(1, true) + } } private fun setNaviButton() { diff --git a/app/src/main/java/com/umc/coumo/presentation/adapter/HomeDetailViewPagerAdapter.kt b/app/src/main/java/com/umc/coumo/presentation/adapter/HomeDetailViewPagerAdapter.kt new file mode 100644 index 0000000..590b907 --- /dev/null +++ b/app/src/main/java/com/umc/coumo/presentation/adapter/HomeDetailViewPagerAdapter.kt @@ -0,0 +1,20 @@ +package com.umc.coumo.presentation.adapter + +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.viewpager2.adapter.FragmentStateAdapter +import com.umc.coumo.presentation.fragment.HomeDetailCouponFragment +import com.umc.coumo.presentation.fragment.HomeDetailInfoFragment + +class HomeDetailViewPagerAdapter(fragment: FragmentActivity): FragmentStateAdapter(fragment) { + val fragments: ArrayList = arrayListOf(HomeDetailInfoFragment(), HomeDetailCouponFragment()) + + override fun getItemCount(): Int { + return fragments.size + } + + override fun createFragment(position: Int): Fragment { + return fragments[position] + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/presentation/adapter/MenuAdapter.kt b/app/src/main/java/com/umc/coumo/presentation/adapter/MenuAdapter.kt new file mode 100644 index 0000000..6b030cc --- /dev/null +++ b/app/src/main/java/com/umc/coumo/presentation/adapter/MenuAdapter.kt @@ -0,0 +1,87 @@ +package com.umc.coumo.presentation.adapter + + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.umc.coumo.databinding.ItemMenuBinding +import com.umc.coumo.databinding.ItemMenuDetailBinding +import com.umc.coumo.domain.model.MenuModel +import com.umc.coumo.utils.ItemDiffCallback + +class MenuAdapter( + private val type: Int +): ListAdapter( + ItemDiffCallback( + onContentsTheSame = {old, new -> old == new}, + onItemsTheSame = {old, new -> old.id == new.id} + ) +) { +companion object { + const val MENU_ITEM = 0 + const val MENU_DETAIL_ITEM = 1 +} + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + val inflater = LayoutInflater.from(parent.context) + return when (type) { + MENU_ITEM -> { + MenuViewHolder(ItemMenuBinding.inflate(inflater, parent,false)) + } + MENU_DETAIL_ITEM -> { + MenuDetailViewHolder(ItemMenuDetailBinding.inflate(inflater, parent,false)) + } + else -> throw IllegalArgumentException("Invalid viewType") + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + val item = getItem(position) + + when (holder) { + is MenuViewHolder -> { + holder.bind(item) + } + is MenuDetailViewHolder -> { + holder.bind(item) + } + } + } + + + + inner class MenuViewHolder( + private val binding: ItemMenuBinding + ): RecyclerView.ViewHolder(binding.root) { + fun bind(item: MenuModel) { + binding.item = item + + itemView.setOnClickListener { + listener?.onItemClick(item.id) + } + } + } + + inner class MenuDetailViewHolder( + private val binding: ItemMenuDetailBinding + ): RecyclerView.ViewHolder(binding.root) { + fun bind(item: MenuModel) { + binding.item = item + + itemView.setOnClickListener { + listener?.onItemClick(item.id) + } + } + } + + interface OnItemClickListener { + fun onItemClick(id:Int) + } + + private var listener: OnItemClickListener? = null + + fun setOnItemClickListener(listener: OnItemClickListener) { + this.listener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/presentation/fragment/HomeDetailCouponFragment.kt b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeDetailCouponFragment.kt new file mode 100644 index 0000000..7e96456 --- /dev/null +++ b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeDetailCouponFragment.kt @@ -0,0 +1,25 @@ +package com.umc.coumo.presentation.fragment + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.activityViewModels +import com.umc.coumo.R +import com.umc.coumo.databinding.FragmentHomeDetailCouponBinding +import com.umc.coumo.domain.type.TabType +import com.umc.coumo.domain.viewmodel.MainViewModel +import com.umc.coumo.utils.binding.BindingFragmentNoneBackPress + +class HomeDetailCouponFragment: BindingFragmentNoneBackPress(R.layout.fragment_home_detail_coupon) { + + private val viewModel: MainViewModel by activityViewModels() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.tvCouponCollection.setOnClickListener { + viewModel.changePageIndex(TabType.COUPON) + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/presentation/fragment/HomeDetailFragment.kt b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeDetailFragment.kt new file mode 100644 index 0000000..a4864c4 --- /dev/null +++ b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeDetailFragment.kt @@ -0,0 +1,44 @@ +package com.umc.coumo.presentation.fragment + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.activityViewModels +import com.umc.coumo.R +import com.umc.coumo.databinding.FragmentHomeDetailBinding +import com.umc.coumo.domain.type.DetailTabType +import com.umc.coumo.domain.viewmodel.HomeViewModel +import com.umc.coumo.presentation.adapter.HomeDetailViewPagerAdapter +import com.umc.coumo.utils.binding.BindingFragmentNoneBackPress + +class HomeDetailFragment: BindingFragmentNoneBackPress(R.layout.fragment_home_detail) { + + private val viewModel: HomeViewModel by activityViewModels() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding.viewModel = viewModel + binding.lifecycleOwner = viewLifecycleOwner + setViewPager() + } + + private fun setViewPager() { + val pagerAdapter = HomeDetailViewPagerAdapter(requireActivity()) + + viewModel.changeTab(DetailTabType.INFO) + + binding.vpStore.apply { + adapter = pagerAdapter + offscreenPageLimit = 1 + isUserInputEnabled = false //스와이프 방지 + } + + binding.tabStoreInfo.setOnClickListener { + binding.vpStore.setCurrentItem(0, true) + viewModel.changeTab(DetailTabType.INFO) + } + binding.tabMyCoupon.setOnClickListener { + binding.vpStore.setCurrentItem(1, true) + viewModel.changeTab(DetailTabType.COUPON) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/presentation/fragment/HomeDetailInfoFragment.kt b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeDetailInfoFragment.kt new file mode 100644 index 0000000..4662bdc --- /dev/null +++ b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeDetailInfoFragment.kt @@ -0,0 +1,48 @@ +package com.umc.coumo.presentation.fragment + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController +import androidx.recyclerview.widget.LinearLayoutManager +import com.umc.coumo.R +import com.umc.coumo.databinding.FragmentHomeDetailInfoBinding +import com.umc.coumo.domain.viewmodel.HomeViewModel +import com.umc.coumo.presentation.adapter.MenuAdapter +import com.umc.coumo.utils.ItemSpacingDecoration +import com.umc.coumo.utils.binding.BindingFragmentNoneBackPress +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class HomeDetailInfoFragment: BindingFragmentNoneBackPress(R.layout.fragment_home_detail_info) { + + private val viewModel : HomeViewModel by activityViewModels () + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setRecyclerView() + } + + private fun setRecyclerView() { + val menuAdapter = MenuAdapter(0) + + binding.rvMenu.apply { + adapter = menuAdapter + layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false) + addItemDecoration(ItemSpacingDecoration(requireContext(),0)) + } + + menuAdapter.setOnItemClickListener(object : MenuAdapter.OnItemClickListener { + override fun onItemClick(id: Int) { + findNavController().navigate(R.id.action_homeDetailFragment_to_homeMenuFragment) + } + }) + + viewModel.menuList.observe(viewLifecycleOwner) { + viewLifecycleOwner.lifecycleScope.launch (Dispatchers.Main) { + menuAdapter.submitList(it) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/presentation/fragment/HomeListFragment.kt b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeListFragment.kt new file mode 100644 index 0000000..19a7eaf --- /dev/null +++ b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeListFragment.kt @@ -0,0 +1,54 @@ +package com.umc.coumo.presentation.fragment + +import android.os.Bundle +import android.view.View +import androidx.core.os.bundleOf +import androidx.navigation.fragment.findNavController +import androidx.recyclerview.widget.LinearLayoutManager +import com.umc.coumo.R +import com.umc.coumo.databinding.FragmentHomeListBinding +import com.umc.coumo.domain.model.StoreCouponCountModel +import com.umc.coumo.presentation.adapter.StoreCouponCountAdapter +import com.umc.coumo.utils.binding.BindingFragmentNoneBackPress + +class HomeListFragment: BindingFragmentNoneBackPress(R.layout.fragment_home_list) { + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.lifecycleOwner = viewLifecycleOwner + + val storeCouponAdapter = StoreCouponCountAdapter() + + binding.rvStore.apply { + adapter = storeCouponAdapter + layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) + } + + storeCouponAdapter.setOnItemClickListener(object : StoreCouponCountAdapter.OnItemClickListener { + override fun onItemClick(id: Int) { + val bundle = bundleOf("id" to id) + findNavController().navigate(R.id.action_homeListFragment_to_homeDetailFragment, bundle) + } + }) + + //테스트 코드 + val list = listOf( + StoreCouponCountModel(1, null,"앙떼띠 로스터리(강남점)", 2), + StoreCouponCountModel(2, null,"앙떼띠 로스터리(강남점)", 5), + StoreCouponCountModel(3, null,"앙떼띠 로스터리(강남점)", 4), + StoreCouponCountModel(4, null,"앙떼띠 로스터리(강남점)", 3), + StoreCouponCountModel(5, null,"앙떼띠 로스터리(강남점)", 10), + StoreCouponCountModel(6, null,"앙떼띠 로스터리(강남점)", 0), + StoreCouponCountModel(11, null,"앙떼띠 로스터리(강남점)", 2), + StoreCouponCountModel(21, null,"앙떼띠 로스터리(강남점)", 5), + StoreCouponCountModel(31, null,"앙떼띠 로스터리(강남점)", 4), + StoreCouponCountModel(41, null,"앙떼띠 로스터리(강남점)", 3), + StoreCouponCountModel(51, null,"앙떼띠 로스터리(강남점)", 10), + StoreCouponCountModel(61, null,"앙떼띠 로스터리(강남점)", 0), + ) + + storeCouponAdapter.submitList(list) + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/presentation/fragment/HomeMainFragment.kt b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeMainFragment.kt new file mode 100644 index 0000000..aebad9e --- /dev/null +++ b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeMainFragment.kt @@ -0,0 +1,19 @@ +package com.umc.coumo.presentation.fragment + +import android.os.Bundle +import android.view.View +import androidx.navigation.fragment.findNavController +import com.umc.coumo.R +import com.umc.coumo.databinding.FragmentHomeMainBinding +import com.umc.coumo.utils.binding.BindingFragment + +class HomeMainFragment: BindingFragment(R.layout.fragment_home_main) { + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.btnTest.setOnClickListener { + findNavController().navigate(R.id.action_homeMainFragment_to_homeSubFragment) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/presentation/fragment/HomeMenuFragment.kt b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeMenuFragment.kt new file mode 100644 index 0000000..258cdcf --- /dev/null +++ b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeMenuFragment.kt @@ -0,0 +1,41 @@ +package com.umc.coumo.presentation.fragment + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.lifecycleScope +import androidx.recyclerview.widget.LinearLayoutManager +import com.umc.coumo.R +import com.umc.coumo.databinding.FragmentHomeMenuBinding +import com.umc.coumo.domain.viewmodel.HomeViewModel +import com.umc.coumo.presentation.adapter.MenuAdapter +import com.umc.coumo.utils.binding.BindingFragmentNoneBackPress +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class HomeMenuFragment: BindingFragmentNoneBackPress(R.layout.fragment_home_menu) { + + private val viewModel : HomeViewModel by activityViewModels () + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setRecyclerView() + + } + + private fun setRecyclerView() { + val menuAdapter = MenuAdapter(1) + + binding.rvMenu.apply { + adapter = menuAdapter + layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) + } + + viewModel.menuList.observe(viewLifecycleOwner) { + viewLifecycleOwner.lifecycleScope.launch (Dispatchers.Main) { + menuAdapter.submitList(it) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/umc/coumo/presentation/fragment/HomeSubFragment.kt b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeSubFragment.kt new file mode 100644 index 0000000..2953efd --- /dev/null +++ b/app/src/main/java/com/umc/coumo/presentation/fragment/HomeSubFragment.kt @@ -0,0 +1,33 @@ +package com.umc.coumo.presentation.fragment + +import android.os.Bundle +import android.view.View +import androidx.navigation.findNavController +import androidx.navigation.fragment.findNavController +import com.umc.coumo.R +import com.umc.coumo.databinding.FragmentHomeSubBinding +import com.umc.coumo.utils.binding.BindingFragment + +class HomeSubFragment: BindingFragment(R.layout.fragment_home_sub) { + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.btnToolbarBack.setOnClickListener { + onBackPressed() + } + } + + override fun onBackPressed() { + super.onBackPressed() + val innerNavController = binding.flHomeSub.findNavController() + val innerBackStackEntryCount = innerNavController.currentBackStack.value.size + + if (innerBackStackEntryCount > 2 ){ + innerNavController.popBackStack() + } else { + findNavController().popBackStack() + } + } + +} \ No newline at end of file diff --git a/app/src/main/res/color/selector_tab_text_color.xml b/app/src/main/res/color/selector_tab_text_color.xml new file mode 100644 index 0000000..8798a7a --- /dev/null +++ b/app/src/main/res/color/selector_tab_text_color.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/icon_chevron_left.xml b/app/src/main/res/drawable/icon_chevron_left.xml new file mode 100644 index 0000000..2591074 --- /dev/null +++ b/app/src/main/res/drawable/icon_chevron_left.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/media.png b/app/src/main/res/drawable/media.png new file mode 100644 index 0000000..8cbdb00 Binary files /dev/null and b/app/src/main/res/drawable/media.png differ diff --git a/app/src/main/res/drawable/shape_new_chip.xml b/app/src/main/res/drawable/shape_new_chip.xml new file mode 100644 index 0000000..b406754 --- /dev/null +++ b/app/src/main/res/drawable/shape_new_chip.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index aa5df32..fd1ed96 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -10,14 +10,12 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home_detail.xml b/app/src/main/res/layout/fragment_home_detail.xml new file mode 100644 index 0000000..db59ca5 --- /dev/null +++ b/app/src/main/res/layout/fragment_home_detail.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home_detail_coupon.xml b/app/src/main/res/layout/fragment_home_detail_coupon.xml new file mode 100644 index 0000000..e36d7b6 --- /dev/null +++ b/app/src/main/res/layout/fragment_home_detail_coupon.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home_detail_info.xml b/app/src/main/res/layout/fragment_home_detail_info.xml new file mode 100644 index 0000000..24e35bb --- /dev/null +++ b/app/src/main/res/layout/fragment_home_detail_info.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home_list.xml b/app/src/main/res/layout/fragment_home_list.xml new file mode 100644 index 0000000..5da5fda --- /dev/null +++ b/app/src/main/res/layout/fragment_home_list.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home_main.xml b/app/src/main/res/layout/fragment_home_main.xml new file mode 100644 index 0000000..0e4a93d --- /dev/null +++ b/app/src/main/res/layout/fragment_home_main.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + +