요구조건
1. 아래로 스크롤시 툴바가 투명해지면서 오른쪽에 썸네일이 보임
2. 아래로 스크롤시 탑으로 가는 버튼 생성 -> 탑으로 이동
3. 스크롤시 탭 레이아웃이 툴바 밑에 고정
상품 상세화면 구조
<CoordinatorLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/abl_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/ctl_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentScrim="@android:color/transparent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:statusBarScrim="@android:color/transparent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="1dp"
app:contentInsetEnd="0dp"
app:contentInsetStart="0dp"
app:layout_collapseMode="pin">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_toolbar_bottom_1dp">
<ImageView
android:id="@+id/iv_back"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:foreground="?attr/selectableItemBackground"
android:onClick="@{()->input.onBackClick()}"
android:paddingHorizontal="19dp"
android:src="@drawable/ic_left_back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
style="@style/NotoMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="21dp"
android:text="@{output.product.name}"
android:textColor="@color/black"
android:textSize="17sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_toolbal_image"
style="@style/NotoRegular"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginEnd="16dp"
android:alpha="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
bind:isRoundCorner="@{3}"
bind:placeholder="@{@drawable/img_placeholder_product_sqaure}"
bind:src="@{output.product.mainImage}"
tools:src="@drawable/img_placeholder_product_sqaure" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.Toolbar>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="?actionBarSize"
android:background="@drawable/bg_border_palegrey_bottom_4dp"
android:paddingBottom="16dp">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vp_thumbnail"
android:layout_width="0dp"
android:layout_height="0dp"
android:clipToPadding="false"
android:overScrollMode="never"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
bind:list="@{output.product.images}" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tl_thumbnail"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
app:layout_constraintBottom_toBottomOf="@id/vp_thumbnail"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:tabBackground="@drawable/ic_ring_white_toxicgreen_selector"
app:tabGravity="center"
app:tabIndicator="@null"
app:tabPaddingEnd="@dimen/dot_padding"
app:tabPaddingStart="@dimen/dot_padding" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/_start_guide"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
app:layout_constraintGuide_begin="16dp" />
...
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tl_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_bottom_pale_grey_1dp"
app:tabIndicatorColor="@color/toxic_green"
app:tabIndicatorFullWidth="true"
app:tabIndicatorHeight="2dp"
app:tabMode="fixed"
app:tabSelectedTextColor="@color/toxic_green"
app:tabTextAppearance="@style/Widget.MaterialComponents.TabLayout.Grey" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/vp_description"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<ImageView
android:id="@+id/iv_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:elevation="5dp"
android:foreground="?attr/selectableItemBackground"
android:src="@drawable/ic_button_top"
android:visibility="gone" />
</CoordinatorLayout>
private val appBarOnOffScrollListener: AppBarLayout.OnOffsetChangedListener by lazy {
AppBarLayout.OnOffsetChangedListener { _, verticalOffset ->
with(viewDataBinding) {
if (ctlLayout.height + verticalOffset < 2 * ViewCompat.getMinimumHeight(ctlLayout)) {
// collapsed (아래로 스크롤 했을때)
ivToolbalImage.alpha = 1f
toolbarLayout.alpha = 0.9f
ivTop.visibility = View.VISIBLE
} else {
// expanded (상단일때)
ivToolbalImage.alpha = 0f
toolbarLayout.alpha = 1f
ivTop.visibility = View.GONE
}
}
}
}
override fun onCreate(){
with(viewDataBinding){
ablLayout.addOnOffsetChangedListener(appBarOnOffScrollListener)
ivTop.setOnClickListener {
ablLayout.setExpanded(true, true)
}
}
}
트러블 기록
- 탑으로 이동한 후에 아래로 스크롤이 먹히지 않는다 ( 위로 올렸다가 내려야함 )
원인
- AppbarLayout가 Expand 됐을때 하단 ViewPager안의 프래그먼트의 리사이클러뷰 포지션이 올라오지 않기 때문.
- 리사이클러뷰의 포지션도 최상단으로 올려줘야함
ivTop.setOnClickListener {
ablLayout.setExpanded(true, true)
val currentFragment = supportFragmentManager.fragments[vpDescription.currentItem]
val productIntroFragment = (currentFragment as ProductIntroFragment)
val rvImage = productIntroFragment.view?.findViewById<RecyclerView>(R.id.rv_image)
rvImage?.smoothScrollToPosition(0)
}
(뷰페이저 안의 리사이클러뷰에 접근해서 스크롤을 탑으로 올리는 코드)
- 눈여겨볼점은 어댑터에서 관리하는 프래그먼트에 접근할때 액티비티의 supportFragmentManager 로 접근할 수 있다.
심지어 인덱스로 접근한다.
'Android' 카테고리의 다른 글
[Refactoring] 여러개의 CheckBox -> Rx 핸들링 (0) | 2021.08.05 |
---|---|
Grid 격자 테두리 그리기(onDraw in RecyclerView.ItemDecoration) (0) | 2021.07.04 |
상품리스트 - 좋아요 - 툴팁 - 트러블 슈팅 (0) | 2021.06.05 |
비동기 함수 - Rx로 변경하기 (0) | 2021.05.14 |
웹뷰 스크롤 전파 (0) | 2021.04.03 |