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

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

Chris Banes
October 09, 2016

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

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