35

I have a strange issue with the CoordinatorLayout and the NestedScrollView (with the design support library 22.2.0)

Using a content smaller than NestedScrollView I should have a fixed content. However trying to scroll up and down the content I can obtain that the content is displaced and never again in their own place.

Here a little sample:enter image description here

Here the code:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_scrollFlags="scroll|enterAlways" />

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

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

        <FrameLayout
            android:paddingTop="24dp"
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="@dimen/padding">

        </FrameLayout>

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

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_action"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="16dp"
        android:visibility="gone"
        android:src="@drawable/ic_done" />

</android.support.design.widget.CoordinatorLayout>
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841

5 Answers5

37

This can also be observed in the cheesesquare demo when removing all but one card in the details fragment.

I was able to solve this (for now) using this class: https://gist.github.com/EmmanuelVinas/c598292f43713c75d18e

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="com.evs.demo.layout.FixedScrollingViewBehavior">
    .....   
</android.support.v4.widget.NestedScrollView>
Paul Burke
  • 25,496
  • 9
  • 66
  • 62
  • 2
    Currently the workaround is a good solution. I think that it is definitely a bug in the support lib. – Gabriele Mariotti Jun 12 '15 at 16:14
  • 2
    Nice fix. However, when the scroll content is smaller than the scroll itself, the scroll still responds and collapses the toolbar. Any idea how to just disable the scroll and the collapse when the scroll is not needed at all (for small content scenarios) – GuillermoMP Jun 13 '15 at 01:02
  • @GuillermoMP Did you manage to fix this? I'm facing the same issue. – Jerry Jul 09 '15 at 10:15
  • This fix works fine after onMeasure. But after starting of the fragment ViewCompat.isLaidOut(appBar) is always false. And this method returns true after, for example, screen-rotation. Where I'm wrong? – VKDev Oct 27 '15 at 08:09
  • Here's a sample App demonstrating a NestedScrollView within a parent ScrollView: https://github.com/AdamSHurwitz/NestedScrolling – AdamHurwitz Jun 21 '16 at 04:27
  • app:layout_behavior= is not let me to enter the class name. how you enter this class? – chari sharma Sep 14 '18 at 09:30
37

I think that it is not a bug in the support lib,just use this

<android.support.v4.widget.NestedScrollView
    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"
    android:fillViewport="true"
    android:layout_gravity="fill_vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">
LiFei
  • 407
  • 3
  • 8
  • I've tried the work around above and works like a charm. Try it! – datienza Aug 06 '15 at 08:05
  • Actually, this does work! At least on 22.2.1. For me it wasn't necessary to have `fillViewPort` though. – Pin Aug 06 '15 at 10:38
  • 4
    I just added 'android:layout_gravity="fill_vertical"' and it worked. Thanks @LiFei. – Suresh Kumar Aug 11 '15 at 12:21
  • This is the correct answer to the question. It isn't a bug in the `NestedScrollView`, and the class used above is unnecessary. – Yash Sampat Aug 31 '15 at 13:01
  • 2
    This definitely doesn't work in my situation, where inside the nested scrollview I have a fragment with an internal recyclerview. If I use this method, the recyclerview scrolls, but the appbar no longer collapses. – Neal Sanche Sep 29 '15 at 01:06
  • I needed the fillViewport...not sure why. – kenyee Jan 17 '17 at 22:25
5

android:layout_gravity="fill_vertical" worked for me too.

Ugo
  • 587
  • 8
  • 12
3

I might be late with my answer but here goes. I was having a similar problem, but none of the above mentioned solutions worked for me. In the end I fixed it by using version 23 of the support library.

...
compileSdkVersion 23
...
targetSdkVersion 23
...
compile 'com.android.support:appcompat-v7:23.1.0'
compile 'com.android.support:support-v4:23.1.0'
compile 'com.android.support:design:23.1.0'
Aleks Nine
  • 249
  • 7
  • 15
  • for interest, switching to v23 of support lib broke my builds with sdk claiming I was not using an `Theme.AppCompat` even though I am. – Richard Le Mesurier Nov 10 '15 at 09:23
  • Well I also had a problem with v23 with Apache's deprecated libraries, but that's a problem for another question. Once you've solved that try to see if this is fixed. – Aleks Nine Nov 10 '15 at 11:41
2

The onMeasureChild() method is called many times during the layout process. Apparently, the key is getting a non-zero value for the child height early in the process. ScrollingViewBehavior fails to do so in the following:

int scrollRange = appBar.getTotalScrollRange();
int height = parent.getHeight() 
             - appBar.getMeasuredHeight()
             + scrollRange;

FixedScrollingviewBehavior fixes this with:

int height = parent.getHeight() 
             - appBar.getMeasuredHeight() 
             + Math.min(scrollRange, parent.getHeight() - heightUsed);

which very early gives height the value of -128, the height of the app bar.

An alternative, close to the original is:

int height = parent.getMeasuredHeight()
             - appBar.getMeasuredHeight()
             + scrollRange;
Jon
  • 555
  • 5
  • 10
  • Could you please explain? Being a beginner, I find it difficult to follow. I tried reading the `ScrollingViewBehavior` class and it's base class `HeaderScrollingViewBehavior`. But I am unable to make sense of it – Kathir Dec 25 '18 at 04:42