Skip to content

Commit a44cc18

Browse files
authored
Merge pull request #62 from boostcampwm-2022/feature/moment-list
모먼트 리스트 스크롤 이슈 해결 및 상세 페이지 이동
2 parents 591acf8 + f2e535d commit a44cc18

File tree

16 files changed

+359
-337
lines changed

16 files changed

+359
-337
lines changed

.github/workflows/android-cd.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
appId: ${{secrets.FIREBASE_APP_ID}}
4343
serviceCredentialsFileContent: ${{ secrets.CREDENTIAL_FILE_CONTENT }}
4444
groups: mogle-testers
45-
file: app/build/outputs/apk/release/app-release-unsigned.apk
45+
file: app/build/outputs/apk/debug/app-debug.apk
4646

4747
- name: action-slack
4848
uses: 8398a7/action-slack@v3.14.0

presentation/src/main/java/com/wakeup/presentation/adapter/BindingAdapters.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ fun bindImageBitmap(view: ImageView, bitmap: Bitmap?) {
3333
view.setImageBitmap(bitmap)
3434
}
3535

36-
@BindingAdapter("gone")
37-
fun bindGone(view: View, shouldBeGone: Boolean) {
38-
view.visibility = if (shouldBeGone) {
36+
@BindingAdapter("isGone")
37+
fun bindGone(view: View, isGone: Boolean) {
38+
view.visibility = if (isGone) {
3939
View.GONE
4040
} else {
4141
View.VISIBLE

presentation/src/main/java/com/wakeup/presentation/adapter/MomentPagingAdapter.kt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
package com.wakeup.presentation.adapter
22

33
import android.view.LayoutInflater
4+
import android.view.View
45
import android.view.ViewGroup
56
import androidx.databinding.DataBindingUtil
7+
import androidx.navigation.findNavController
8+
import androidx.navigation.fragment.findNavController
69
import androidx.paging.PagingDataAdapter
710
import androidx.recyclerview.widget.DiffUtil
811
import androidx.recyclerview.widget.ListAdapter
912
import androidx.recyclerview.widget.RecyclerView
1013
import com.wakeup.presentation.R
1114
import com.wakeup.presentation.databinding.ItemMomentBinding
1215
import com.wakeup.presentation.model.MomentModel
16+
import com.wakeup.presentation.ui.map.MapFragmentDirections
1317
import timber.log.Timber
1418

1519
class MomentPagingAdapter :
@@ -37,12 +41,19 @@ class MomentPagingAdapter :
3741
private val binding: ItemMomentBinding
3842
) : RecyclerView.ViewHolder(binding.root) {
3943
init {
40-
itemView.setOnClickListener {
41-
// TODO: 모먼트 페이지 이동
42-
Timber.d("모먼트 클릭")
44+
itemView.setOnClickListener { view ->
45+
binding.moment?.let { moment ->
46+
navigateToMoment(moment, view)
47+
}
4348
}
4449
}
4550

51+
private fun navigateToMoment(moment: MomentModel, view: View) {
52+
val direction =
53+
MapFragmentDirections.actionMapFragmentToMomentDetailFragment(moment)
54+
view.findNavController().navigate(direction)
55+
}
56+
4657
fun bind(moment: MomentModel) {
4758
with(binding) {
4859
this.moment = moment

presentation/src/main/java/com/wakeup/presentation/ui/detail/MomentDetailFragment.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import android.view.View
77
import android.view.ViewGroup
88
import androidx.fragment.app.Fragment
99
import androidx.lifecycle.lifecycleScope
10+
import androidx.navigation.fragment.findNavController
1011
import androidx.navigation.fragment.navArgs
1112
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
1213
import androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_DRAGGING
1314
import androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_IDLE
1415
import com.wakeup.presentation.R
1516
import com.wakeup.presentation.adapter.DetailPictureAdapter
1617
import com.wakeup.presentation.databinding.FragmentMomentDetailBinding
18+
import com.wakeup.presentation.util.setToolbar
1719
import dagger.hilt.android.AndroidEntryPoint
1820
import kotlinx.coroutines.FlowPreview
1921
import kotlinx.coroutines.flow.MutableStateFlow
@@ -43,12 +45,21 @@ class MomentDetailFragment : Fragment() {
4345
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
4446
super.onViewCreated(view, savedInstanceState)
4547

48+
initToolbar()
4649
initAnimator()
4750
initViewPagerAdapter()
4851
initMoment()
4952
collectPageChangedFlow()
5053
}
5154

55+
private fun initToolbar() {
56+
setToolbar(
57+
toolbar = binding.tbDetailMoment,
58+
titleId = R.string.moment,
59+
onBackClick = { findNavController().navigateUp() }
60+
)
61+
}
62+
5263
private fun initAnimator() {
5364
indicatorAnimator =
5465
ObjectAnimator.ofFloat(binding.tvIndicator, ALPHA_PROPERTY, START_ALPHA, END_ALPHA)

presentation/src/main/java/com/wakeup/presentation/ui/map/MapFragment.kt

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import androidx.lifecycle.Lifecycle
1313
import androidx.lifecycle.lifecycleScope
1414
import androidx.lifecycle.repeatOnLifecycle
1515
import androidx.navigation.fragment.findNavController
16+
import androidx.paging.map
17+
import androidx.recyclerview.widget.RecyclerView
1618
import com.google.android.material.bottomsheet.BottomSheetBehavior
1719
import com.google.android.material.snackbar.Snackbar
1820
import com.google.android.material.textfield.MaterialAutoCompleteTextView
@@ -43,6 +45,13 @@ class MapFragment : Fragment(), OnMapReadyCallback {
4345
private lateinit var locationSource: FusedLocationSource
4446
private lateinit var mapHelper: MapHelper
4547

48+
private val adapterDataObserver = object : RecyclerView.AdapterDataObserver() {
49+
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
50+
super.onItemRangeMoved(fromPosition, toPosition, itemCount)
51+
binding.bottomSheet.rvMoments.scrollToPosition(0)
52+
}
53+
}
54+
4655
override fun onCreateView(
4756
inflater: LayoutInflater, container: ViewGroup?,
4857
savedInstanceState: Bundle?,
@@ -58,10 +67,19 @@ class MapFragment : Fragment(), OnMapReadyCallback {
5867
initMap()
5968
initLocation()
6069
initBottomSheet()
61-
initTestButton()
70+
setAdapterListener()
6271

6372
collectMoments()
6473
updateMoments()
74+
75+
}
76+
77+
private fun setAdapterListener() {
78+
momentAdapter.registerAdapterDataObserver(adapterDataObserver)
79+
80+
momentAdapter.addLoadStateListener {
81+
binding.bottomSheet.hasMoments = momentAdapter.itemCount > 0
82+
}
6583
}
6684

6785
private fun updateMoments() {
@@ -90,20 +108,6 @@ class MapFragment : Fragment(), OnMapReadyCallback {
90108
}
91109
}
92110

93-
// TODO 추후 삭제
94-
private fun initTestButton() {
95-
val bitmap =
96-
BitmapFactory.decodeResource(requireContext().resources, R.drawable.sample_image2)
97-
val picture = PictureModel(bitmap)
98-
99-
binding.btnTest.setOnClickListener {
100-
val fakeMoment = FakeMomentFactory.createMomentsWithSampleImage(picture, 1)
101-
val action =
102-
MapFragmentDirections.actionMapFragmentToMomentDetailFragment(fakeMoment.first())
103-
findNavController().navigate(action)
104-
}
105-
}
106-
107111
private fun setMenus(binding: BottomSheetBinding) {
108112
val items = listOf(
109113
getString(R.string.most_recent),
@@ -203,6 +207,7 @@ class MapFragment : Fragment(), OnMapReadyCallback {
203207
}
204208

205209
override fun onDestroyView() {
210+
momentAdapter.unregisterAdapterDataObserver(adapterDataObserver)
206211
binding.unbind()
207212
super.onDestroyView()
208213
}

presentation/src/main/res/layout/bottom_sheet.xml

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
xmlns:app="http://schemas.android.com/apk/res-auto"
44
xmlns:tools="http://schemas.android.com/tools">
55

6+
<data>
7+
8+
<variable
9+
name="hasMoments"
10+
type="boolean" />
11+
</data>
12+
613
<androidx.coordinatorlayout.widget.CoordinatorLayout
714
android:layout_width="match_parent"
815
android:layout_height="match_parent">
@@ -49,17 +56,33 @@
4956

5057
</com.google.android.material.textfield.TextInputLayout>
5158

52-
<androidx.recyclerview.widget.RecyclerView
53-
android:id="@+id/rv_moments"
54-
android:layout_width="match_parent"
59+
<FrameLayout
60+
android:layout_width="0dp"
5561
android:layout_height="0dp"
56-
android:layout_marginTop="@dimen/normal_100"
57-
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
62+
app:layout_constraintBottom_toBottomOf="parent"
5863
app:layout_constraintEnd_toEndOf="parent"
5964
app:layout_constraintStart_toStartOf="parent"
60-
app:layout_constraintTop_toBottomOf="@id/text_field"
61-
app:layout_constraintBottom_toBottomOf="parent"
62-
tools:listitem="@layout/item_moment" />
65+
app:layout_constraintTop_toBottomOf="@id/text_field">
66+
67+
<androidx.recyclerview.widget.RecyclerView
68+
android:id="@+id/rv_moments"
69+
android:layout_width="match_parent"
70+
android:layout_height="match_parent"
71+
android:layout_marginTop="@dimen/normal_100"
72+
app:isGone="@{!hasMoments}"
73+
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
74+
tools:listitem="@layout/item_moment" />
75+
76+
<TextView
77+
style="@style/TextAppearance.Mogle.Title"
78+
android:layout_width="match_parent"
79+
android:layout_height="match_parent"
80+
android:gravity="center"
81+
android:text="지금 이 순간을 기록해보세요."
82+
app:isGone="@{hasMoments}" />
83+
84+
</FrameLayout>
85+
6386

6487
</androidx.constraintlayout.widget.ConstraintLayout>
6588

0 commit comments

Comments
 (0)