Android

TroubleShooting With AppbarLayout expand

그란. 2021. 6. 6. 21:22

요구조건

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 로 접근할 수 있다. 

심지어 인덱스로 접근한다.