简体   繁体   中英

Collapsing toolbar layout with NestedScrollView doesnt scroll smoothly

I have a NestedScrollView with CollapsingToolbarLayout and I would like to make it work smoothly.

My problem is when scrolling up from content, my Collapsing Toolbar doesn't auto expand but is blocked when it hits top. Then i need to scroll up again in order to expand toolbar.

I would like to achieve smooth scrolling up from content that would auto expand my CollapsingToolbarLayout

Here is my code:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/product_detail_main_content"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:apptools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="true"
            android:foregroundGravity="bottom|right"
            android:foregroundTintMode="add"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

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

       /*
           CONTENT
       */

    </LinearLayout>
</android.support.v4.widget.NestedScrollView>

I found some similar questions but none of the answers worked for me.

What kind of content is inside LinearLayout ?

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

   /*
       CONTENT
   */

</LinearLayout>

If one of the content is recyclerview, the reason why collapsing toolbar does not respond to scrolling is because NestedScrollView does not call AppBarLayout.Behavour class when it receive scroll events from recyclerview. that is, when a scroll happens in recyclerview, recyclerview dispatches/passes the scroll progress to NestedScrollView . NestedScrollView receives the scroll event but does nothing with it.

Inside nestedscrollview class

@overide
public void onNestedpreScroll(View target,int dx, int dy, int[] consumed){
         //Do nothing
}

To overcome this and make appbarlayout expand/collapse when scrolling recyclerview, just create a custom class that extends NestedScrollView and overide the above method and call method dispatchNestedPreScroll() which informs the appbarlayout of the scroll event and make it respond to it.

  public class CustomNestedScrollView extends NestedScrollView{

    public CustomNestedScrollView(Context context) {
    super(context);
    }

    public CustomNestedScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
    }

    public CustomNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    }

  @overide
  public void onNestedPreScroll(View target, int dx, int dy, int[] consumed){
    dispatchNestedPreScroll(dx,dy,consumed,null);
  }
}

And then use this class in your layout.xml

<com.my.package.CustomNestedScrollView
    android:id="@+id/scroll"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

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

   /*
       CONTENT
   */

</LinearLayout>

I have solved that problem by SmoothAppBarLayout
Link: https://github.com/henrytao-me/smooth-app-bar-layout

Add this dependency in your app level build.gradle

compile "me.henrytao:smooth-app-bar-layout:25.3.1.0"

Mark that child of NestedScrollView should have clickable and focusable true.
This is XML Layout

<?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 .../>
</data>

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/coordinatorLayoutPlaceDetail"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/adViewPlaceDetail"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <me.henrytao.smoothappbarlayout.SmoothAppBarLayout
            android:id="@+id/appBarLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <android.support.design.widget.CollapsingToolbarLayout
                android:id="@+id/collapsing_toolbar"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:contentScrim="?attr/colorPrimary"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">
                <!--app:layout_scrollInterpolator="@android:anim/accelerate_decelerate_interpolator"-->

                <ImageView
                    android:id="@+id/imgOfPlace"
                    android:layout_width="match_parent"
                    android:layout_height="200dp"
                    android:adjustViewBounds="true"
                    android:contentDescription="@string/app_name"
                    android:scaleType="fitXY"
                    android:src="@drawable/placeholder"
                    app:layout_collapseMode="parallax" />

                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:layout_collapseMode="pin"
                    app:layout_scrollFlags="scroll|enterAlways" />

            </android.support.design.widget.CollapsingToolbarLayout>

        </me.henrytao.smoothappbarlayout.SmoothAppBarLayout>

        <android.support.v4.widget.NestedScrollView
            android:id="@+id/nestedScrollView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fillViewport="true"
            android:overScrollMode="never"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <android.support.constraint.ConstraintLayout
                android:id="@+id/constraintLayoutInNestedScroll"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:focusable="true"
                android:focusableInTouchMode="true">

                <YOUR CONTENT VIEWS>

            </android.support.constraint.ConstraintLayout>

        </android.support.v4.widget.NestedScrollView>

    </android.support.design.widget.CoordinatorLayout>

    <com.google.android.gms.ads.AdView xmlns:ads="http://schemas.android.com/apk/res-auto"
        android:id="@+id/adViewPlaceDetail"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        ads:adSize="SMART_BANNER"
        ads:adUnitId="..."
        ads:layout_constraintBottom_toBottomOf="parent"
        ads:layout_constraintEnd_toEndOf="parent"
        ads:layout_constraintStart_toStartOf="parent" />

</android.support.constraint.ConstraintLayout>

.java类中设置RecyclerView适配器后添加以下代码:

ViewCompat.setNestedScrollingEnabled(View-name, false);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM