Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#7 [ui] 온보딩 - 테마 선택 뷰 #12

Merged
merged 13 commits into from
Jan 9, 2024
12 changes: 7 additions & 5 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@
tools:targetApi="31">
<activity
android:name=".ui.main.MainActivity"
android:exported="false"
android:screenOrientation="portrait" />

<activity
android:name=".ui.main.happy.HappyActivity"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
Expand All @@ -33,6 +28,13 @@
</intent-filter>
</activity>

<activity
android:name=".ui.main.happy.HappyActivity"
android:exported="true"
android:screenOrientation="portrait"></activity>
<activity
android:name=".ui.onboarding.OnboardingActivity"
android:exported="false"></activity>
</application>

</manifest>
8 changes: 8 additions & 0 deletions app/src/main/java/com/sopetit/softie/domain/entity/Theme.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.sopetit.softie.domain.entity

data class Theme(
Comment on lines +1 to +3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍👍

val themeId: Int,
val name: String,
val iconImageUrl: String,
val backgroudnImageUrl: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.sopetit.softie.ui.onboarding

import android.os.Bundle
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.sopetit.softie.R
import com.sopetit.softie.databinding.FragmentOnboardingChoiceBearBinding
import com.sopetit.softie.util.binding.BindingFragment

class BearChoiceFragment :
BindingFragment<FragmentOnboardingChoiceBearBinding>(R.layout.fragment_onboarding_choice_bear) {

private lateinit var viewModel: OnboardingViewModel

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

viewModel = ViewModelProvider(requireActivity()).get(OnboardingViewModel::class.java)
binding.viewModel = viewModel

initChangeFragment()
}

private fun initChangeFragment() {
binding.clOnboardingChoiceBear.setOnClickListener {
viewModel.changeBearNameChoiceView()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.sopetit.softie.ui.onboarding

import android.os.Bundle
import androidx.activity.viewModels
import androidx.fragment.app.Fragment
import com.sopetit.softie.R
import com.sopetit.softie.databinding.ActivityOnboardingBinding
import com.sopetit.softie.ui.onboarding.routinechoice.RoutineChoiceFragment
import com.sopetit.softie.ui.onboarding.themechoice.ChoiceThemeFragment
import com.sopetit.softie.util.binding.BindingActivity

class OnboardingActivity :
BindingActivity<ActivityOnboardingBinding>(R.layout.activity_onboarding) {

private val viewModel by viewModels<OnboardingViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.viewModel = viewModel

initMakeFragment()
initChangeFragment()
}

private fun initMakeFragment() {
val currentFragment = supportFragmentManager.findFragmentById(R.id.fcv_onboarding_fragment)
if (currentFragment == null) {
viewModel.changeBearChoiceView()
supportFragmentManager.beginTransaction()
.add(R.id.fcv_onboarding_fragment, BearChoiceFragment())
.commit()
}
}

private fun initChangeFragment() {
initChangeRoutineChoice()
initChangeSetBearName()
initChangeThemeChoice()
}

private fun initChangeSetBearName() {
viewModel.bearNameChoiceView.observe(this) { bearNameChoice ->
if (bearNameChoice) {
changeFragment(SetBearNameFragment())
}
}
}

private fun initChangeThemeChoice() {
viewModel.themeChoiceView.observe(this) { themeChoiceView ->
if (themeChoiceView) {
changeFragment(ChoiceThemeFragment())
}
}
}

private fun initChangeRoutineChoice() {
viewModel.routineChoiceView.observe(this) { routineChoiceView ->
if (routineChoiceView) {
changeFragment(RoutineChoiceFragment())
}
}
}

private fun changeFragment(fragment: Fragment) {
supportFragmentManager.beginTransaction()
.replace(R.id.fcv_onboarding_fragment, fragment)
.commit()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.sopetit.softie.ui.onboarding

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class OnboardingViewModel : ViewModel() {

private val _bearChoiceView: MutableLiveData<Boolean> = MutableLiveData(false)
val bearChoiceView: LiveData<Boolean>
get() = _bearChoiceView

private val _bearNameChoiceView: MutableLiveData<Boolean> = MutableLiveData(false)
val bearNameChoiceView: LiveData<Boolean>
get() = _bearNameChoiceView

private val _themeChoiceView: MutableLiveData<Boolean> = MutableLiveData(false)
val themeChoiceView: LiveData<Boolean>
get() = _themeChoiceView

private val _routineChoiceView: MutableLiveData<Boolean> = MutableLiveData(false)
val routineChoiceView: LiveData<Boolean>
get() = _routineChoiceView

fun changeBearChoiceView() {
_bearChoiceView.value = true
}

fun changeBearNameChoiceView() {
_bearNameChoiceView.value = true
}

fun changeThemeChoiceView() {
_themeChoiceView.value = true
}
Comment on lines +33 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다른 view 값들에 대해서는 false 처리를 안해도 나중에 문제가 안될지,,!!

  • 온보딩 과정 중에는 뒤로가기 버튼을 막아야 되겠죠..?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 고민을 좀 했는데.. 일단은 지금 온보딩 과정 중에 뒤로가기 로직이 없는 상태라서 그냥 true로만 설정했습니다...! 나중에 유저 로직이 바뀌게 되면 코드 수정하겠습니당


fun changeRoutineChoiceView() {
_routineChoiceView.value = true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.sopetit.softie.ui.onboarding

import android.os.Bundle
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.sopetit.softie.R
import com.sopetit.softie.databinding.FragmentOnboardingSetBearNameBinding
import com.sopetit.softie.util.binding.BindingFragment

class SetBearNameFragment :
BindingFragment<FragmentOnboardingSetBearNameBinding>(R.layout.fragment_onboarding_set_bear_name) {

private lateinit var viewModel: OnboardingViewModel

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

viewModel = ViewModelProvider(requireActivity()).get(OnboardingViewModel::class.java)
binding.viewModel = viewModel

initChangeFragment()
}

private fun initChangeFragment() {
binding.clOnboardingSetBearName.setOnClickListener {
viewModel.changeThemeChoiceView()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.sopetit.softie.ui.onboarding.routinechoice

import android.os.Bundle
import android.view.View
import com.sopetit.softie.R
import com.sopetit.softie.databinding.FragmentOnboardingChoiceRoutineBinding
import com.sopetit.softie.util.binding.BindingFragment

class RoutineChoiceFragment :
BindingFragment<FragmentOnboardingChoiceRoutineBinding>(R.layout.fragment_onboarding_choice_routine) {

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.sopetit.softie.ui.onboarding.themechoice

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.sopetit.softie.databinding.ItemOnboardingChoiceThemeBinding
import com.sopetit.softie.domain.entity.Theme
import com.sopetit.softie.util.ItemDiffCallback

class ChoiceThemeAdapter :
ListAdapter<Theme, ChoiceThemeAdapter.ChoiceThemeViewHolder>(
ItemDiffCallback<Theme>(
onItemsTheSame = { old, new -> old.themeId == new.themeId },
onContentsTheSame = { old, new -> old == new }
)
) {

class ChoiceThemeViewHolder(private val binding: ItemOnboardingChoiceThemeBinding) :
RecyclerView.ViewHolder(binding.root) {
fun onBind(data: Theme) {
binding.tvThemeName.text = data.name
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChoiceThemeViewHolder {
val binding = ItemOnboardingChoiceThemeBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return ChoiceThemeViewHolder(binding)
}

override fun onBindViewHolder(holder: ChoiceThemeViewHolder, position: Int) {
holder.onBind(currentList[position])
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.sopetit.softie.ui.onboarding.themechoice

import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.view.View
import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import com.sopetit.softie.R
import com.sopetit.softie.databinding.FragmentOnboardingChoiceThemeBinding
import com.sopetit.softie.ui.onboarding.OnboardingViewModel
import com.sopetit.softie.util.binding.BindingFragment

class ChoiceThemeFragment :
BindingFragment<FragmentOnboardingChoiceThemeBinding>(R.layout.fragment_onboarding_choice_theme) {

private lateinit var viewModel: OnboardingViewModel
private val themeViewModel by viewModels<ChoiceThemeViewModel>()

private var _choiceThemeAdapter: ChoiceThemeAdapter? = null
private val choiceThemeAdapter
get() = requireNotNull(_choiceThemeAdapter)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

viewModel = ViewModelProvider(requireActivity()).get(OnboardingViewModel::class.java)
binding.viewModel = viewModel

binding.tvOnboardingChoiceThemeSpeech.text =
SpannableStringBuilder(getString(R.string.onboarding_choice_theme_speech)).apply {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setSpan이 멘트의 특정부분만 인덱싱해서 색을 바꾸는 부분인가요?
잘 배워갑니다...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네! 이렇게 하면 textview를 여러개 만들 필요가 없습니당

setSpan(
ForegroundColorSpan(
ContextCompat.getColor(
requireActivity(),
R.color.onboarding_speech
)
),
SPAN_START,
SPAN_END,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}

initMakeThemeAdapter()
}

private fun initMakeThemeAdapter() {
_choiceThemeAdapter = ChoiceThemeAdapter()
binding.rvOnboardingChoiceTheme.apply {
layoutManager = GridLayoutManager(requireContext(), 3)
adapter = choiceThemeAdapter
}
themeViewModel.mockThemeList.observe(viewLifecycleOwner) {
choiceThemeAdapter.submitList(it)
}
}

private fun initChangeFragment() {
// TODO 버튼 클릭시 '루틴 선택' fragment로 화면 전환 (밑의 주석 삭제 예정)
// binding.clOnboardingChoiceTheme.setOnClickListener {
// viewModel.changeRoutineChoiceView()
// }
}

companion object {
const val SPAN_START = 5
const val SPAN_END = 8
}
}
Loading