Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Nested scrolling: living life on the edge (DevF...

Avatar for Chris Banes Chris Banes
October 09, 2016

Nested scrolling: living life on the edge (DevFest Tokyo 2016)

Avatar for Chris Banes

Chris Banes

October 09, 2016
Tweet

More Decks by Chris Banes

Other Decks in Technology

Transcript

  1. Nested scrolling views was difficult <ScrollView> <LinearLayout> <!-- Some content

    --> <ListView> <!-- More content which scrolls --> </ListView> </LinearLayout> </ScrollView>
  2. void setNestedScrollingEnabled(boolean enabled); boolean isNestedScrollingEnabled(); boolean startNestedScroll(int axes); boolean hasNestedScrollingParent();

    boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed,
 int[] offsetInWindow); boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
 int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow); boolean dispatchNestedPreFling(float velocityX, float velocityY); boolean dispatchNestedFling(float velocityX, float velocityY,
 boolean consumed); void stopNestedScroll(); Sending
  3. void setNestedScrollingEnabled(boolean enabled); boolean isNestedScrollingEnabled(); boolean startNestedScroll(int axes); boolean hasNestedScrollingParent();

    boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed,
 int[] offsetInWindow); boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
 int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow); boolean dispatchNestedPreFling(float velocityX, float velocityY); boolean dispatchNestedFling(float velocityX, float velocityY,
 boolean consumed); void stopNestedScroll(); Sending
  4. boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed,
 int[] offsetInWindow); boolean

    dispatchNestedScroll(int dxConsumed, int dyConsumed,
 int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow); boolean dispatchNestedPreFling(float velocityX, float velocityY); boolean dispatchNestedFling(float velocityX, float velocityY,
 boolean consumed); Sending
  5. boolean onStartNestedScroll(View child, View target,
 int nestedScrollAxes); void onNestedScrollAccepted(View child,

    View target,
 int nestedScrollAxes); void onStopNestedScroll(View target); int getNestedScrollAxes(); Receiving void onNestedPreScroll(View target, int dx, int dy, int[] consumed); void onNestedScroll(View target, int dxConsumed, int dyConsumed,
 int dxUnconsumed, int dyUnconsumed); boolean onNestedPreFling(View target, float velocityX,
 float velocityY); boolean onNestedFling(View target, float velocityX,
 float velocityY, boolean consumed);
  6. boolean onStartNestedScroll(View child, View target,
 int nestedScrollAxes); void onNestedScrollAccepted(View child,

    View target,
 int nestedScrollAxes); void onStopNestedScroll(View target); int getNestedScrollAxes(); Receiving void onNestedPreScroll(View target, int dx, int dy, int[] consumed); void onNestedScroll(View target, int dxConsumed, int dyConsumed,
 int dxUnconsumed, int dyUnconsumed); boolean onNestedPreFling(View target, float velocityX,
 float velocityY); boolean onNestedFling(View target, float velocityX,
 float velocityY, boolean consumed);
  7. Receiving void onNestedPreScroll(View target, int dx, int dy, int[] consumed);

    void onNestedScroll(View target, int dxConsumed, int dyConsumed,
 int dxUnconsumed, int dyUnconsumed); boolean onNestedPreFling(View target, float velocityX,
 float velocityY); boolean onNestedFling(View target, float velocityX,
 float velocityY, boolean consumed);
  8. Pre vs Non-Pre The view then scrolls the remainder Pre-scroll

    events allow a parent to intercept and consume the event
  9. Pre vs Non-Pre Scroll events allow the parent to observe

    what the view scrolled The view then scrolls the remainder Pre-scroll events allow a parent to intercept and consume the event
  10. ACTION_DOWN // Initialise VelocityTracker and add event mVelocityTracker.addMovement(ev); int y

    = ev.getY(); // 1020 mInitialMotionY = y; mLastMotionY = y; startNestedScroll(SCROLL_AXIS_VERTICAL);
  11. ACTION_DOWN startNestedScroll(SCROLL_AXIS_VERTICAL); @Override boolean onStartNestedScroll(View child, View target, int axes)

    { // child == LinearLayout // target == ListView // axes == SCROLL_AXIS_VERTICAL return true; }
  12. ACTION_DOWN startNestedScroll(SCROLL_AXIS_VERTICAL); @Override void onNestedScrollAccepted(View child, View target, int axes)

    { // child == LinearLayout // target == ListView // axes == SCROLL_AXIS_VERTICAL }
  13. ACTION_MOVE int[] mScrollConsumed = new int[2]; int y = ev.getY();

    // 1010 int dy = mLastMotionY - y; // -10 if (dispatchNestedPreScroll(0, dy, mScrollConsumed, ...)) { dy -= mScrollConsumed[1]; } // INSERT Move children by remaining dy // TODO call dispatchNestedScroll()
  14. ACTION_MOVE int[] mScrollConsumed = new int[2]; int y = ev.getY();

    // 1010 int dy = mLastMotionY - y; // -10 if (dispatchNestedPreScroll(0, dy, mScrollConsumed, ...)) { dy -= mScrollConsumed[1]; } // INSERT Move children by remaining dy // TODO call dispatchNestedScroll()
  15. ACTION_MOVE @Override void onNestedPreScroll(View target, int dx, int dy, int[]

    consumed) { // dx = 0, dy = -10, consumed = int[2] int amountWeConsume = doSomethingWithPreScroll(dy); // consumed[0] = y, consumed[1] = x consumed[1] = amountWeConsume; } dispatchNestedPreScroll(0, dy, mScrollConsumed, ...)
  16. ACTION_MOVE @Override void onNestedPreScroll(View target, int dx, int dy, int[]

    consumed) { // dx = 0, dy = -10, consumed = int[2] int amountWeConsume = doSomethingWithPreScroll(dy); // consumed[0] = y, consumed[1] = x consumed[1] = amountWeConsume; } dispatchNestedPreScroll(0, dy, mScrollConsumed, ...) // -3
  17. ACTION_MOVE int[] mScrollConsumed = new int[2]; int y = ev.getY();

    // 1010 int dy = mLastMotionY - y; // -10 if (dispatchNestedPreScroll(0, dy, mScrollConsumed, ...)) { dy -= mScrollConsumed[1]; } // INSERT Move children by remaining dy // TODO call dispatchNestedScroll() // -3 remember // dy = -7
  18. ACTION_MOVE int[] mScrollConsumed = new int[2]; int y = ev.getY();

    // 1010 int dy = mLastMotionY - y; // -10 if (dispatchNestedPreScroll(0, dy, mScrollConsumed, ...)) { dy -= mScrollConsumed[1]; } // INSERT Move children by remaining dy // TODO call dispatchNestedScroll()
  19. ACTION_MOVE // INSERT Move children by remaining dy dispatchNestedScroll(0, dy,

    0, unconsumedY, ...) @Override void onNestedScroll(View target,
 int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { // Do something if you wish }
  20. ACTION_UP float velY = ...; if (!dispatchNestedPreFling(0, velY)) { //

    Parent hasn't consumed fling, lets fling // and let the parent observe dispatchNestedFling(0, velY, ...); fling(velY); } stopNestedScroll();
  21. ACTION_UP float velY = ...; if (!dispatchNestedPreFling(0, velY)) { //

    Parent hasn't consumed fling, lets fling // and let the parent observe dispatchNestedFling(0, velY, ...); fling(velY); } stopNestedScroll();
  22. ACTION_UP dispatchNestedPreFling(0, velY); @Override boolean onNestedPreFling(View target, float velX, float

    velY) { // return true to consume the whole fling, // false to let the view handle it }
  23. ACTION_UP float velY = ...; if (!dispatchNestedPreFling(0, velY)) { //

    Parent hasn't consumed fling, lets fling // and let the parent observe dispatchNestedFling(0, velY, ...); fling(velY); } stopNestedScroll();
  24. ACTION_UP float velY = ...; if (!dispatchNestedPreFling(0, velY)) { //

    Parent hasn't consumed fling, lets fling // and let the parent observe dispatchNestedFling(0, velY, ...); fling(velY); } stopNestedScroll();
  25. > NESTED SCROLLING: LIVING LIFE ON THE EDGE Indirect Nested

    Scrolling INDIRECT NESTED SCROLLING Work in progress
  26. void setNestedIndirectScrollingEnabled(boolean enabled); boolean isNestedIndirectScrollingEnabled(); boolean startNestedIndirectScroll(int axes); boolean dispatchNestedIndirectPreScroll(int

    dx, int dy,
 int[] consumed); boolean dispatchNestedIndirectScroll(int dxConsumed,
 int dyConsumed, int dxUnconsumed, int dyUnconsumed); boolean hasNestedIndirectScrollingParent(); void stopNestedIndirectScroll(); Sending
  27. boolean onStartNestedIndirectScroll(View child, View target,
 int axes); void onNestedIndirectScrollAccepted(View child,

    View target,
 int axes); void onNestedIndirectPreScroll(View target, int dx, int dy,
 int[] consumed); void onNestedIndirectScroll(View target, int dxConsumed,
 int dyConsumed, int dxUnconsumed, int dyUnconsumed); void onStopNestedIndirectScroll(View child); Receiving