Skip to content

Commit

Permalink
[AN] feat: 내 강아지 상세 화면 (#116)
Browse files Browse the repository at this point in the history
  • Loading branch information
junjange authored Jul 19, 2024
1 parent 428bf04 commit 6b98496
Show file tree
Hide file tree
Showing 21 changed files with 468 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.woowacourse.friendogly.presentation.ui.dogdetail

import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.databinding.BindingAdapter
import com.woowacourse.friendogly.R
import java.time.LocalDate
import java.time.format.DateTimeFormatter

@BindingAdapter("setUpIndicator")
fun LinearLayout.bindSetUpIndicator(size: Int) {
removeAllViews()

val layoutParams =
LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
).apply {
leftMargin = 30
}

repeat(size) { index ->
ImageView(context).apply {
val drawableId =
if (index == 0) R.drawable.shape_indicator_active else R.drawable.shape_indicator_inactive

setImageDrawable(ContextCompat.getDrawable(context, drawableId))
this.layoutParams = layoutParams
addView(this)
}
}
}

@BindingAdapter("currentIndicator")
fun LinearLayout.bindCurrentIndicator(currentPage: Int) {
if (childCount == 0) return
val position = currentPage % childCount
for (idx in 0 until childCount) {
val imageView = getChildAt(idx) as ImageView
val drawableId =
if (idx == position) R.drawable.shape_indicator_active else R.drawable.shape_indicator_inactive
imageView.setImageDrawable(ContextCompat.getDrawable(context, drawableId))
}
}

@BindingAdapter("genderDrawable")
fun ImageView.bindGenderDrawable(gender: String) {
if (gender == "수컷") {
this.setImageResource(R.drawable.img_dog_male)
} else {
this.setImageResource(R.drawable.img_dog_female)
}
}

@BindingAdapter("neuteredTitle")
fun TextView.bindNeuteredTitle(isNeutered: Boolean) {
if (isNeutered) {
this.apply {
text = "중성화를 했어요"
visibility = View.VISIBLE
}
} else {
this.visibility = View.GONE
}
}

@BindingAdapter("dogSize")
fun TextView.bindDogSize(sizeType: String) {
text =
when (sizeType) {
"소형견" -> "소형견이에요"
"중형견" -> "중현견이에요"
"대형견" -> "대형견이에요"
else -> ""
}
}

@BindingAdapter("dogBirthday")
fun TextView.binDogBirthday(birthday: LocalDate) {
val formatter = DateTimeFormatter.ofPattern("yyyy.MM")
val formattedDate = birthday.format(formatter)
this.text = formattedDate
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.woowacourse.friendogly.presentation.ui.dogdetail

import androidx.fragment.app.viewModels
import androidx.navigation.fragment.navArgs
import androidx.viewpager2.widget.ViewPager2
import com.woowacourse.friendogly.R
import com.woowacourse.friendogly.databinding.FragmentDogDetailBinding
import com.woowacourse.friendogly.presentation.base.BaseFragment
import com.woowacourse.friendogly.presentation.ui.dogdetail.adapter.DogDetailAdapter
import com.woowacourse.friendogly.presentation.ui.mypage.MyPageViewModel.Companion.dogs

class DogDetailFragment : BaseFragment<FragmentDogDetailBinding>(R.layout.fragment_dog_detail) {
private val viewModel: DogDetailViewModel by viewModels()
private val args: DogDetailFragmentArgs by navArgs()

private val adapter: DogDetailAdapter by lazy { DogDetailAdapter() }

override fun initViewCreated() {
initDataBinding()
initObserve()
initAdapter()
}

private fun initDataBinding() {
binding.vm = viewModel

binding.vpDogDetail.registerOnPageChangeCallback(
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
viewModel.updateCurrentPage(position)
}
},
)
}

private fun initAdapter() {
binding.vpDogDetail.adapter = adapter
}

private fun initObserve() {
viewModel.uiState.observe(this) { uiState ->
adapter.submitList(uiState.dogs)
binding.vpDogDetail.setCurrentItem(uiState.dogs.size, false)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.woowacourse.friendogly.presentation.ui.dogdetail

import com.woowacourse.friendogly.presentation.ui.mypage.Dog

data class DogDetailUiState(
val dogs: List<Dog> = emptyList(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.woowacourse.friendogly.presentation.ui.dogdetail

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.woowacourse.friendogly.presentation.base.BaseViewModel
import com.woowacourse.friendogly.presentation.ui.mypage.MyPageViewModel.Companion.dogs

class DogDetailViewModel : BaseViewModel() {
private val _uiState: MutableLiveData<DogDetailUiState> = MutableLiveData(DogDetailUiState())
val uiState: LiveData<DogDetailUiState> get() = _uiState

private val _currentPage: MutableLiveData<Int> = MutableLiveData(MIDDLE_PAGE)
val currentPage: LiveData<Int> get() = _currentPage

init {
fetchDummy()
}

private fun fetchDummy() {
val state = _uiState.value ?: return
_uiState.value = state.copy(dogs = dogs)
_currentPage.value = MIDDLE_PAGE - (MIDDLE_PAGE) % dogs.size
}

fun updateCurrentPage(page: Int) {
_currentPage.value = page
}

companion object {
private const val MIDDLE_PAGE = Int.MAX_VALUE / 2
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.woowacourse.friendogly.presentation.ui.dogdetail.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.ItemDogDetailBinding
import com.woowacourse.friendogly.presentation.ui.mypage.Dog

class DogDetailAdapter : ListAdapter<Dog, DogDetailAdapter.ViewHolder>(DogItemDiffCallback) {
init {
setHasStableIds(true)
}

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

override fun getItemCount(): Int = Int.MAX_VALUE

override fun onBindViewHolder(
holder: ViewHolder,
position: Int,
) {
holder.bind(getItem(position % currentList.size))
}

class ViewHolder(private val binding: ItemDogDetailBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(item: Dog) {
binding.dog = item
}
}

internal object DogItemDiffCallback : DiffUtil.ItemCallback<Dog>() {
override fun areItemsTheSame(
oldItem: Dog,
newItem: Dog,
): Boolean = oldItem.name == newItem.name

override fun areContentsTheSame(
oldItem: Dog,
newItem: Dog,
): Boolean = oldItem == newItem
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.woowacourse.friendogly.presentation.ui.mypage

interface MyPageActionHandler {
fun navigateToDogDetail()
fun navigateToDogDetail(id: Long)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@ class MyPageFragment : BaseFragment<FragmentMyPageBinding>(R.layout.fragment_my_
viewModel.navigateAction.observeEvent(this) { action ->
when (action) {
is MyPageNavigationAction.NavigateToSetting -> TODO()
is MyPageNavigationAction.NavigateToDogDetail -> TODO()
is MyPageNavigationAction.NavigateToDogDetail ->
navigate(MyPageFragmentDirections.actionMyPageFragmentToDogDetailFragment(action.id))

is MyPageNavigationAction.NavigateToDogRegister ->
navigate(MyPageFragmentDirections.actionMyPageFragmentToRegisterDogFragment())
navigate(
MyPageFragmentDirections.actionMyPageFragmentToRegisterDogFragment(),
)

is MyPageNavigationAction.NavigateToProfileEdit -> TODO()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ sealed interface MyPageNavigationAction {

data object NavigateToDogRegister : MyPageNavigationAction

data object NavigateToDogDetail : MyPageNavigationAction
data class NavigateToDogDetail(val id: Long) : MyPageNavigationAction
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class MyPageViewModel : BaseViewModel(), MyPageActionHandler {
_navigateAction.emit(MyPageNavigationAction.NavigateToDogRegister)
}

override fun navigateToDogDetail() {
_navigateAction.emit(MyPageNavigationAction.NavigateToDogDetail)
override fun navigateToDogDetail(id: Long) {
_navigateAction.emit(MyPageNavigationAction.NavigateToDogDetail(id = id))
}

companion object {
Expand Down
7 changes: 7 additions & 0 deletions android/app/src/main/res/anim/enter_from_right.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="300"
android:fromXDelta="0"
android:toXDelta="-100%p" />
</set>
9 changes: 9 additions & 0 deletions android/app/src/main/res/anim/exit_to_right.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="300"
android:propertyName="x"
android:valueFrom="0"
android:valueTo="400dp"
android:valueType="floatType" />
</set>
Binary file added android/app/src/main/res/drawable/img_acorm.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">

<gradient
android:angle="90"
android:startColor="#80000000"
android:type="linear" />
</shape>
10 changes: 10 additions & 0 deletions android/app/src/main/res/drawable/shape_indicator_active.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/blue" />

<size
android:width="8dp"
android:height="8dp" />

</shape>
10 changes: 10 additions & 0 deletions android/app/src/main/res/drawable/shape_indicator_inactive.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/gray05" />

<size
android:width="5dp"
android:height="5dp" />

</shape>
44 changes: 44 additions & 0 deletions android/app/src/main/res/layout/fragment_dog_detail.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

<variable
name="vm"
type="com.woowacourse.friendogly.presentation.ui.dogdetail.DogDetailViewModel" />

</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vp_dog_detail"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<LinearLayout
android:id="@+id/linearLayout_indicator"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="16dp"
android:gravity="center"
android:orientation="horizontal"
android:padding="15dp"
app:currentIndicator="@{vm.currentPage}"
app:layout_constraintBottom_toBottomOf="@+id/vp_dog_detail"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:setUpIndicator="@{vm.uiState.dogs.size()}" />


</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
9 changes: 5 additions & 4 deletions android/app/src/main/res/layout/item_dog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:background="@drawable/rect_white_fill_10"
android:clipToOutline="true">
android:clipToOutline="true"
app:onSingleClick="@{() -> actionHandler.navigateToDogDetail(0)}">

<ImageView
android:id="@+id/iv_product_thumbnail"
android:id="@+id/iv_dog_thumbnail"
urlToImage="@{dog.image}"
android:layout_width="200dp"
android:layout_height="200dp"
Expand All @@ -38,7 +39,7 @@
tools:src="@drawable/ic_launcher_background" />

<TextView
android:id="@+id/tv_product_name"
android:id="@+id/tv_dog_name"
style="@style/Theme.AppCompat.TextView.Regular.Black.Size16"
android:layout_width="0dp"
android:layout_height="wrap_content"
Expand All @@ -50,7 +51,7 @@
android:paddingBottom="10dp"
android:text="@{dog.name}"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="@+id/iv_product_thumbnail"
app:layout_constraintBottom_toBottomOf="@+id/iv_dog_thumbnail"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
Expand Down
Loading

0 comments on commit 6b98496

Please sign in to comment.