Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Seamless nested scrolling (Android)

We've all been advised against nesting views that contain a scrolling mechanism. However, in the latest Android release (5.0), the Phone app caught my attention with what seems to be a ListView inside of a ScrollView.

What really intrigued me was that the scrolling mechanism switched from the ScrollView to the ListView seamlessly.

Notice the content above the tabs is pushed out of view before the actual ListView begins scrolling.

I've tried duplicating this myself, but ended up unsuccessful. Here is the basic approach I was taking...

enter image description here

With a single, continuous touch event (no lifting of the finger) ...

As user scrolls, the ListView slowly covers up the ImageView. Once the ImageView is 100% covered and the ListView takes up the entire screen, the ListView begins to scroll.

I'm currently listening to touch events on the ListView and if the top has been reached, call requestDisallowInterceptTouchEvent on the ListView, i.e.

@Override
public boolean onTouch(View v, MotionEvent event) {
  if (listViewAtTop) {
    v.requestDisallowInterceptTouchEvent(true);
  } else {
    v.requestDisallowInterceptTouchEvent(false);
  }
  return false;
}

The switching scrolling context works, only if you lift your finger and continue scrolling.

Is there a different approach that will achieve the desired effect?

like image 270
Alex Fu Avatar asked Nov 27 '14 02:11

Alex Fu


3 Answers

Android 5.0 Lollipop (API 21) added nested scrolling support.

From what I can tell, both ListView (AbsListView) and ScrollView support this now (if running on API 21), but it must be enabled on the scrolling views.

There are two ways, by calling setNestedScrollingEnabled(true) or with the layout attribute android:nestedScrollingEnabled="true" (which is undocumented)

To learn about how it works, or to support this for a custom widget, the key methods are these:

  • onStartNestedScroll

  • onNestedScrollAccepted

  • onNestedPreScroll

  • onNestedScroll

  • onStopNestedScroll

Unfortunately, there is no guide or training which explains how this works other than the JavaDoc itself which is rather light and there are no examples other than ScrollView.

like image 146
Mark Renouf Avatar answered Sep 22 '22 10:09

Mark Renouf


Add latest support package 'com.android.support:support-v4:22.1.1' to your project. And try this:

<android.support.v4.widget.NestedScrollView
        android:id="@+id/nScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">

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

By default nested scrolling is Enabled.

like image 42
M. Usman Khan Avatar answered Sep 23 '22 10:09

M. Usman Khan


While trying to figure out how to solve this issue myself, I found this question first; however, the answer didn't really go into too much detail. I did find a lot of good resources, so if anyone else finds themselves looking for this, I'll link them below. A term for this effect is "Sticky Scrolling".


An article talking about "Synchronized Scrolling".

http://www.pushing-pixels.org/2011/07/18/android-tips-and-tricks-synchronized-scrolling.html


A good video showcasing some Android scrolling tricks, "Quick Return" and "Sticky Scrolling".

https://www.youtube.com/watch?v=PL9s0IJ9oiI

Code: https://code.google.com/p/romannurik-code/source/browse/misc/scrolltricks


And lastly, here is another one showcasing the same effect using a listView instead of a ScrollView.

https://www.youtube.com/watch?v=rk-tLisxSgM

Code: https://github.com/jatago/list_sticky_scroll_trick

like image 28
Advice-Dog Avatar answered Sep 21 '22 10:09

Advice-Dog