diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageActionHandler.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageActionHandler.kt new file mode 100644 index 000000000..a578edf2e --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageActionHandler.kt @@ -0,0 +1,5 @@ +package com.woowacourse.friendogly.presentation.ui.mypage + +interface MyPageActionHandler { + fun navigateToDogDetail() +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageFragment.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageFragment.kt index c1a5e92db..d7ca554df 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageFragment.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageFragment.kt @@ -1,9 +1,43 @@ package com.woowacourse.friendogly.presentation.ui.mypage +import androidx.fragment.app.viewModels import com.woowacourse.friendogly.R import com.woowacourse.friendogly.databinding.FragmentMyPageBinding import com.woowacourse.friendogly.presentation.base.BaseFragment +import com.woowacourse.friendogly.presentation.base.observeEvent +import com.woowacourse.friendogly.presentation.ui.mypage.adapter.DogProfileAdapter class MyPageFragment : BaseFragment(R.layout.fragment_my_page) { - override fun initViewCreated() {} + private val viewModel: MyPageViewModel by viewModels() + + private val adapter: DogProfileAdapter by lazy { DogProfileAdapter(viewModel) } + + override fun initViewCreated() { + initDataBinding() + initAdapter() + initObserve() + } + + private fun initDataBinding() { + binding.vm = viewModel + } + + private fun initAdapter() { + binding.rvDogProfile.adapter = adapter + } + + private fun initObserve() { + viewModel.navigateAction.observeEvent(this) { action -> + when (action) { + is MyPageNavigationAction.NavigateToSetting -> TODO() + is MyPageNavigationAction.NavigateToDogDetail -> TODO() + is MyPageNavigationAction.NavigateToDogRegister -> TODO() + is MyPageNavigationAction.NavigateToProfileEdit -> TODO() + } + } + + viewModel.uiState.observe(viewLifecycleOwner) { uiState -> + adapter.submitList(uiState.dogs) + } + } } diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageNavigationAction.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageNavigationAction.kt new file mode 100644 index 000000000..eebbfa150 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageNavigationAction.kt @@ -0,0 +1,11 @@ +package com.woowacourse.friendogly.presentation.ui.mypage + +sealed interface MyPageNavigationAction { + data object NavigateToProfileEdit : MyPageNavigationAction + + data object NavigateToSetting : MyPageNavigationAction + + data object NavigateToDogRegister : MyPageNavigationAction + + data object NavigateToDogDetail : MyPageNavigationAction +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageUiState.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageUiState.kt new file mode 100644 index 000000000..04d274ce3 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageUiState.kt @@ -0,0 +1,21 @@ +package com.woowacourse.friendogly.presentation.ui.mypage + +import java.time.LocalDate + +data class MyPageUiState( + val nickname: String = "", + val email: String = "", + val profilePath: String? = null, + val dogs: List = emptyList(), +) + +// TODO 더미 데이터 모델 +data class Dog( + val name: String, + val description: String, + val birthDate: LocalDate, + val sizeType: String, + val gender: String, + val isNeutered: Boolean, + val image: String, +) diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageViewModel.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageViewModel.kt new file mode 100644 index 000000000..311a22fd5 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/MyPageViewModel.kt @@ -0,0 +1,81 @@ +package com.woowacourse.friendogly.presentation.ui.mypage + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.woowacourse.friendogly.presentation.base.BaseViewModel +import com.woowacourse.friendogly.presentation.base.Event +import com.woowacourse.friendogly.presentation.base.emit +import java.time.LocalDate + +class MyPageViewModel : BaseViewModel(), MyPageActionHandler { + private val _uiState: MutableLiveData = MutableLiveData(MyPageUiState()) + val uiState: LiveData get() = _uiState + + private val _navigateAction: MutableLiveData> = + MutableLiveData(null) + val navigateAction: LiveData> get() = _navigateAction + + init { + fetchDummy() + } + + private fun fetchDummy() { + val state = _uiState.value ?: return + + _uiState.value = + state.copy( + nickname = "손흥민", + email = "tottenham@gmail.com", + dogs = dogs, + ) + } + + fun navigateToDogRegister() { + _navigateAction.emit(MyPageNavigationAction.NavigateToDogRegister) + } + + override fun navigateToDogDetail() { + _navigateAction.emit(MyPageNavigationAction.NavigateToDogDetail) + } + + companion object { + val dog = + Dog( + name = "땡이", + description = "강인해요", + birthDate = LocalDate.now(), + sizeType = "", + gender = "", + isNeutered = true, + image = "https://github.com/user-attachments/assets/9329234e-e47d-4fc5-b4b5-9f2a827b60b1", + ) + val dogs = + listOf( + dog, + dog.copy( + name = "초코", + image = "https://github.com/user-attachments/assets/a344d355-8b00-4e08-a33f-08db58010b07", + ), + dog.copy( + name = "도토리", + image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", + ), + dog.copy( + name = "도토리", + image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", + ), + dog.copy( + name = "도토리", + image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", + ), + dog.copy( + name = "도토리", + image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", + ), + dog.copy( + name = "도토리", + image = "https://petsstore.co.kr/web/product/big/202401/dc7c18de083f0ab58060b4ec82321028.jpg", + ), + ) + } +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/adapter/DogProfileAdapter.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/adapter/DogProfileAdapter.kt new file mode 100644 index 000000000..a5f7bb118 --- /dev/null +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/ui/mypage/adapter/DogProfileAdapter.kt @@ -0,0 +1,53 @@ +package com.woowacourse.friendogly.presentation.ui.mypage.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.woowacourse.friendogly.databinding.ItemDogBinding +import com.woowacourse.friendogly.presentation.ui.mypage.Dog +import com.woowacourse.friendogly.presentation.ui.mypage.MyPageActionHandler + +class DogProfileAdapter( + private val actionHandler: MyPageActionHandler, +) : ListAdapter(DogItemDiffCallback) { + init { + setHasStableIds(true) + } + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int, + ): ViewHolder { + val inflater = LayoutInflater.from(parent.context) + val binding = ItemDogBinding.inflate(inflater, parent, false) + binding.actionHandler = actionHandler + return ViewHolder(binding) + } + + override fun onBindViewHolder( + holder: ViewHolder, + position: Int, + ) { + holder.bind(getItem(position)) + } + + class ViewHolder(private val binding: ItemDogBinding) : RecyclerView.ViewHolder(binding.root) { + fun bind(item: Dog) { + binding.dog = item + } + } + + internal object DogItemDiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame( + oldItem: Dog, + newItem: Dog, + ): Boolean = oldItem.name == newItem.name + + override fun areContentsTheSame( + oldItem: Dog, + newItem: Dog, + ): Boolean = oldItem == newItem + } +} diff --git a/android/app/src/main/java/com/woowacourse/friendogly/presentation/utils/GlideImageBindingAdapters.kt b/android/app/src/main/java/com/woowacourse/friendogly/presentation/utils/GlideImageBindingAdapters.kt index deaf91dcb..78caf9cd1 100644 --- a/android/app/src/main/java/com/woowacourse/friendogly/presentation/utils/GlideImageBindingAdapters.kt +++ b/android/app/src/main/java/com/woowacourse/friendogly/presentation/utils/GlideImageBindingAdapters.kt @@ -31,3 +31,27 @@ fun ImageView.bindProfile1000(bitmap: Bitmap?) { .transform(CenterCrop(), RoundedCorners(1000)) .into(this) } + +@BindingAdapter("glideProfile1000") +fun ImageView.bindProfile1000(profilePath: String?) { + if (profilePath == null) { + this.setImageResource(R.drawable.img_dog) + return + } + + Glide.with(context) + .asBitmap() + .load(profilePath) + .transform(CenterCrop(), RoundedCorners(1000)) + .into(this) +} + +@BindingAdapter("urlToImage") +fun ImageView.bindUrlToImage(imageUrl: String?) { + imageUrl?.let { url -> + Glide.with(context) + .load(url) + .centerCrop() + .into(this) + } +} diff --git a/android/app/src/main/res/drawable/rect_black_gradient_fill.xml b/android/app/src/main/res/drawable/rect_black_gradient_fill.xml new file mode 100644 index 000000000..19c54f764 --- /dev/null +++ b/android/app/src/main/res/drawable/rect_black_gradient_fill.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/android/app/src/main/res/drawable/rect_gray01_fill_16.xml b/android/app/src/main/res/drawable/rect_gray01_fill_16.xml new file mode 100644 index 000000000..62e1dfbf0 --- /dev/null +++ b/android/app/src/main/res/drawable/rect_gray01_fill_16.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/android/app/src/main/res/layout/fragment_my_page.xml b/android/app/src/main/res/layout/fragment_my_page.xml index 5dd7ba28b..44f3c7406 100644 --- a/android/app/src/main/res/layout/fragment_my_page.xml +++ b/android/app/src/main/res/layout/fragment_my_page.xml @@ -3,11 +3,140 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> + + + + + + android:layout_height="match_parent" + android:background="@color/white"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/layout/item_dog.xml b/android/app/src/main/res/layout/item_dog.xml new file mode 100644 index 000000000..95790b94a --- /dev/null +++ b/android/app/src/main/res/layout/item_dog.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index f0598c325..056d37cd4 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -14,6 +14,10 @@ 뒤로가기 버튼을\n한번 더 누르면 종료됩니다. + + 프로필 편집 + 등록하기 + 멍멍짖기