Part of the content of a CollapsingToolbarLayout is getting sticky on top, when used with viewpager and recyclerview

社会主义新天地 提交于 2020-05-23 04:31:45

问题


I am trying to implement a layout like this:

The issue is that when scrolling up the card touches the toolbar and it does not go up anymore like this:

I want it to scroll up till the viewpager to fills the screen ie, at least the rectangle card, should scroll up beyond the toolbar(Even the tabLayout can also scroll up). But I don't want it to stay sticky at the top.

The main layout is here:

 <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:showIn="@layout/activity_main">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/background_dark"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/toolbarCollapse"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="190dp"
                android:minHeight="190dp"
                android:src="@drawable/ic_launcher_foreground"
                app:layout_collapseMode="parallax" />


            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?actionBarSize"
                app:layout_collapseMode="pin" />

        </com.google.android.material.appbar.CollapsingToolbarLayout>


    </com.google.android.material.appbar.AppBarLayout>


    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        app:behavior_overlapTop="90dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:id="@+id/lin"
            android:nestedScrollingEnabled="false"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <include layout="@layout/debit_card_item" />


            <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabLayout"
                android:layout_width="match_parent"
                android:layout_height="?actionBarSize"
                android:layout_marginTop="40dp"
                android:background="?attr/colorPrimary" />


            <androidx.viewpager.widget.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1" />

        </LinearLayout>
    </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

The fragments of the pager are inside a NestedScrollView like this:

<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rcView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</androidx.core.widget.NestedScrollView>

Things that I tried:

  1. I have tried to remove the NestedScrollView above the linear layout and added the app:behavior_overlapTop="90dp" app:layout_behavior="@string/appbar_scrolling_view_behavior" to the linear layout. but it's still giving me the same output.
  2. Set the height of the view pager statically(gave the same result).

-->>>EDIT<<< 3. I thought of a workaround and I am trying to add custom behavior to my LinearLayout in my mainActivity. so as to reduce the margin-bottom and height of the rectangular card. It is giving good results when I fling and close the collapsing toolbar. But when I hold down and scroll, the screen is flickering as shown below:

My Custom behavior is

class CustomHeaderBehavior : AppBarLayout.ScrollingViewBehavior {
    private var mContext: Context

    var height = 0
    var width = 0
    var marginBottom = 0
    var firstTime = true

    constructor(
        context: Context,
        attrs: AttributeSet?
    ) : super(context, attrs) {
        mContext = context
    }

    constructor(
        context: Context?,
        attrs: AttributeSet?,
        mContext: Context
    ) : super(context, attrs) {
        this.mContext = mContext
    }

    override fun layoutDependsOn(
        parent: CoordinatorLayout,
        child: View,
        dependency: View
    ): Boolean {
        return super.layoutDependsOn(parent, child, dependency)
    }

    override fun onDependentViewChanged(
        parent: CoordinatorLayout,
        childP: View,
        dependency: View
    ): Boolean {
        val child = childP.findViewById<RelativeLayout>(R.id.cardParent)
        val maxScroll: Int = (dependency as AppBarLayout).totalScrollRange
        val percentage =
            abs(dependency.y) / maxScroll.toFloat()
        Log.d("Behavx","D.y "+abs(dependency.y)+ " m s "+maxScroll+ " p "+percentage)
        val lp: LinearLayout.LayoutParams =
            child.layoutParams as LinearLayout.LayoutParams
        if(firstTime){
            height = child.height
            width = child.width
            marginBottom = lp.bottomMargin
            firstTime = false
        }
        Log.d("Behaviour", "P "+ ((1-(percentage))*100).toString() +" H " +height+ " U H " +(height*(((1-(percentage))*100))/100) )
//        lp.bottomMargin = ((marginBottom*(((1-(percentage))*100))/100) - ((height*((((percentage))*100))/100))).toInt()
        lp.bottomMargin = ((marginBottom*(((1-(percentage))*100))/100)).toInt() //updating margin bottom
        lp.height = ((height*(((1-(percentage))*100))/100)).toInt() //updating height

        child.layoutParams = lp
        child.alpha = 1 - (percentage * 4)
        return super.onDependentViewChanged(parent, childP, dependency)

    }


    companion object {
        fun getToolbarHeight(context: Context): Int {
            var result = 0
            val tv = TypedValue()
            if (context.theme.resolveAttribute(R.attr.actionBarSize, tv, true)) {
                result = TypedValue.complexToDimensionPixelSize(
                    tv.data,
                    context.resources.displayMetrics
                )
            }
            return result
        }
    }
}

The flicker seems to be happening because the dependency.y is becoming wrong randomly, while I hold down and scroll and update the height of the card(if I only update the margin flicker is not occurring). For some reason controlling the width is happening smoothly. But unfortunately, that's not helping me here.

  1. I also tried to do something similar by adding an offsetChangedListener to the app bar like this:

    appBar.addOnOffsetChangedListener(OnOffsetChangedListener { appBarLayout, verticalOffset -> if (abs(verticalOffset) == appBarLayout.totalScrollRange) { // Collapsed cardParent.visibility = View.GONE } else { //Expanded cardParent.visibility = View.VISIBLE } })

But I am still getting the flicker

I have added the sample project here: github link The custom behavior is pushed to a new branch custom_behaviour


回答1:


Finally Solved my issue. I added the card inside the collapsing layout like Kalyans answer and added a dummy view and a -ve margin to the card to have the overlap behavior effect like

<com.google.android.material.appbar.CollapsingToolbarLayout
        android:id="@+id/toolbarCollapse"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        app:contentScrim="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?actionBarSize"
            app:layout_collapseMode="pin" />

        <View
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="#000" />

        <include
            layout="@layout/debit_card_item"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="-90dp"
            app:layout_collapseMode="parallax" />
    </LinearLayout>

</com.google.android.material.appbar.CollapsingToolbarLayout>

I have also pushed my code to the github.




回答2:


In order to achieve that effect, the card layout should be inside the collapsing toolbar.

Try replacing this:

<ImageView
            android:layout_width="match_parent"
            android:layout_height="190dp"
            android:minHeight="190dp"
            android:src="@drawable/ic_launcher_foreground"
            app:layout_collapseMode="parallax" />

with:

<include layout="@layout/debit_card_item"
            android:layout_width="match_parent"
            android:layout_height="190dp"
            android:minHeight="190dp"
            android:layout_marginTop="32dp"
            android:layout_marginBottom="72dp"
            app:layout_collapseMode="parallax"/>

and remove <include layout="@layout/debit_card_item" /> in the NestedScrollView.

Hope this helps.



来源:https://stackoverflow.com/questions/61640784/part-of-the-content-of-a-collapsingtoolbarlayout-is-getting-sticky-on-top-when

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!