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

How to implement custom LayoutManager

How to implement custom LayoutManager

Avatar for Moyuru Aizawa

Moyuru Aizawa

March 08, 2019
Tweet

More Decks by Moyuru Aizawa

Other Decks in Programming

Transcript

  1. ‣ PO-BZPVU$IJMESFO ‣ TDSPMM7FSUJDBMMZ#ZTDSPMM)PSJ[POUBMMZ#Z ‣ TDSPMM5P ‣ TNPPUI4DSPMM5P ‣ DPNQVUF7FSUJDBM4DSPMM&YUFOUDPNQVUF)PSJ[POUBM4DSPMM&YUFOU

    ‣ DPNQVUF7FSUJDBM4DSPMM0GGTFUDPNQVUF)PSJ[POUBM4DSPMM0GGTFU ‣ DPNQVUF7FSUJDBM4DSPMM3BOHFDPNQVUF)PSJ[POUBM4DSPMM3BOHF ‣ *UFN1SFGFUDI ‣ *UFN%FDPSBUJPOT ‣ *UFN"OJNBUPST ‣ 1SFEJDUJWF"OJNBUJPOT ‣ ʜ -BZPVU.BOBHFSͷؔ਺ػೳ
  2. ‣ PO-BZPVU$IJMESFO ‣ TDSPMM7FSUJDBMMZ#ZTDSPMM)PSJ[POUBMMZ#Z ‣ TDSPMM5P ‣ TNPPUI4DSPMM5P ‣ DPNQVUF7FSUJDBM4DSPMM&YUFOUDPNQVUF)PSJ[POUBM4DSPMM&YUFOU

    ‣ DPNQVUF7FSUJDBM4DSPMM0GGTFUDPNQVUF)PSJ[POUBM4DSPMM0GGTFU ‣ DPNQVUF7FSUJDBM4DSPMM3BOHFDPNQVUF)PSJ[POUBM4DSPMM3BOHF ‣ *UFN1SFGFUDI ‣ *UFN%FDPSBUJPOT ‣ *UFN"OJNBUPST ‣ 1SFEJDUJWF"OJNBUJPOT ‣ ʜ -BZPVU.BOBHFSͷؔ਺ػೳ
  3. ‣ PO-BZPVU$IJMESFO ‣ TDSPMM7FSUJDBMMZ#ZTDSPMM)PSJ[POUBMMZ#Z ‣ TDSPMM5P ‣ TNPPUI4DSPMM5P ‣ DPNQVUF7FSUJDBM4DSPMM&YUFOUDPNQVUF)PSJ[POUBM4DSPMM&YUFOU

    ‣ DPNQVUF7FSUJDBM4DSPMM0GGTFUDPNQVUF)PSJ[POUBM4DSPMM0GGTFU ‣ DPNQVUF7FSUJDBM4DSPMM3BOHFDPNQVUF)PSJ[POUBM4DSPMM3BOHF ‣ *UFN1SFGFUDI ‣ *UFN%FDPSBUJPOT ‣ *UFN"OJNBUPST ‣ 1SFEJDUJWF"OJNBUJPOT ‣ ʜ -BZPVU.BOBHFSͷؔ਺ػೳ
  4. ‣ PO-BZPVU$IJMESFO ‣ TDSPMM7FSUJDBMMZ#ZTDSPMM)PSJ[POUBMMZ#Z ‣ TDSPMM5P ‣ TNPPUI4DSPMM5P ‣ DPNQVUF7FSUJDBM4DSPMM&YUFOUDPNQVUF)PSJ[POUBM4DSPMM&YUFOU

    ‣ DPNQVUF7FSUJDBM4DSPMM0GGTFUDPNQVUF)PSJ[POUBM4DSPMM0GGTFU ‣ DPNQVUF7FSUJDBM4DSPMM3BOHFDPNQVUF)PSJ[POUBM4DSPMM3BOHF ‣ *UFN1SFGFUDI ‣ *UFN%FDPSBUJPOT ‣ *UFN"OJNBUPST ‣ 1SFEJDUJWF"OJNBUJPOT ‣ ʜ -BZPVU.BOBHFSͷؔ਺ػೳ
  5. ‣ PO-BZPVU$IJMESFO ‣ TDSPMM7FSUJDBMMZ#ZTDSPMM)PSJ[POUBMMZ#Z ‣ TDSPMM5P ‣ TNPPUI4DSPMM5P ‣ DPNQVUF7FSUJDBM4DSPMM&YUFOUDPNQVUF)PSJ[POUBM4DSPMM&YUFOU

    ‣ DPNQVUF7FSUJDBM4DSPMM0GGTFUDPNQVUF)PSJ[POUBM4DSPMM0GGTFU ‣ DPNQVUF7FSUJDBM4DSPMM3BOHFDPNQVUF)PSJ[POUBM4DSPMM3BOHF ‣ *UFN1SFGFUDI ‣ *UFN%FDPSBUJPOT ‣ *UFN"OJNBUPST ‣ 1SFEJDUJWF"OJNBUJPOT ‣ ʜ -BZPVU.BOBHFSͷؔ਺ػೳ
  6. ‣ PO-BZPVU$IJMESFO ‣ TDSPMM7FSUJDBMMZ#ZTDSPMM)PSJ[POUBMMZ#Z ‣ TDSPMM5P ‣ TNPPUI4DSPMM5P ‣ DPNQVUF7FSUJDBM4DSPMM&YUFOUDPNQVUF)PSJ[POUBM4DSPMM&YUFOU

    ‣ DPNQVUF7FSUJDBM4DSPMM0GGTFUDPNQVUF)PSJ[POUBM4DSPMM0GGTFU ‣ DPNQVUF7FSUJDBM4DSPMM3BOHFDPNQVUF)PSJ[POUBM4DSPMM3BOHF ‣ *UFN1SFGFUDI ‣ *UFN%FDPSBUJPOT ‣ *UFN"OJNBUPST ‣ 1SFEJDUJWF"OJNBUJPOT ‣ ʜ -BZPVU.BOBHFSͷؔ਺ػೳ
  7. ‣ PO-BZPVU$IJMESFO ‣ TDSPMM7FSUJDBMMZ#ZTDSPMM)PSJ[POUBMMZ#Z ‣ TDSPMM5P ‣ TNPPUI4DSPMM5P ‣ DPNQVUF7FSUJDBM4DSPMM&YUFOUDPNQVUF)PSJ[POUBM4DSPMM&YUFOU

    ‣ DPNQVUF7FSUJDBM4DSPMM0GGTFUDPNQVUF)PSJ[POUBM4DSPMM0GGTFU ‣ DPNQVUF7FSUJDBM4DSPMM3BOHFDPNQVUF)PSJ[POUBM4DSPMM3BOHF ‣ *UFN1SFGFUDI ‣ *UFN%FDPSBUJPOT ‣ *UFN"OJNBUPST ‣ 1SFEJDUJWF"OJNBUJPOT ‣ ʜ -BZPVU.BOBHFSͷؔ਺ػೳ
  8. private fun addRow(position: Int, offsetY: Int, isAppend: Boolean, recycler: Recycler):

    Int { val view = recycler.getViewForPosition(position) addView(view, if (isAppend) -1 else 0) measureChildWithMargins(view, 0, 0) val height = getDecoratedMeasuredHeight(view) val width = getDecoratedMeasuredWidth(view) val top = if (isAppend) offsetY else offsetY - height val bottom = top + height layoutDecoratedWithMargins( view, parentLeft, top, parentLeft + width, bottom) return height } PO-BZPVU$IJMESFO
  9. private fun addRow(position: Int, offsetY: Int, isAppend: Boolean, recycler: Recycler):

    Int { val view = recycler.getViewForPosition(position) addView(view, if (isAppend) -1 else 0) measureChildWithMargins(view, 0, 0) val height = getDecoratedMeasuredHeight(view) val width = getDecoratedMeasuredWidth(view) val top = if (isAppend) offsetY else offsetY - height val bottom = top + height layoutDecoratedWithMargins( view, parentLeft, top, parentLeft + width, bottom) return height } PO-BZPVU$IJMESFO
  10. private fun addRow(position: Int, offsetY: Int, isAppend: Boolean, recycler: Recycler):

    Int { val view = recycler.getViewForPosition(position) addView(view, if (isAppend) -1 else 0) measureChildWithMargins(view, 0, 0) val height = getDecoratedMeasuredHeight(view) val width = getDecoratedMeasuredWidth(view) val top = if (isAppend) offsetY else offsetY - height val bottom = top + height layoutDecoratedWithMargins( view, parentLeft, top, parentLeft + width, bottom) return height } PO-BZPVU$IJMESFO
  11. private fun addRow(position: Int, offsetY: Int, isAppend: Boolean, recycler: Recycler):

    Int { val view = recycler.getViewForPosition(position) addView(view, if (isAppend) -1 else 0) measureChildWithMargins(view, 0, 0) val height = getDecoratedMeasuredHeight(view) val width = getDecoratedMeasuredWidth(view) val top = if (isAppend) offsetY else offsetY - height val bottom = top + height layoutDecoratedWithMargins( view, parentLeft, top, parentLeft + width, bottom) return height } PO-BZPVU$IJMESFO
  12. private fun addRow(position: Int, offsetY: Int, isAppend: Boolean, recycler: Recycler):

    Int { val view = recycler.getViewForPosition(position) addView(view, if (isAppend) -1 else 0) measureChildWithMargins(view, 0, 0) val height = getDecoratedMeasuredHeight(view) val width = getDecoratedMeasuredWidth(view) val top = if (isAppend) offsetY else offsetY - height val bottom = top + height layoutDecoratedWithMargins( view, parentLeft, top, parentLeft + width, bottom) return height } PO-BZPVU$IJMESFO
  13. private fun addRow(position: Int, offsetY: Int, isAppend: Boolean, recycler: Recycler):

    Int { val view = recycler.getViewForPosition(position) addView(view, if (isAppend) -1 else 0) measureChildWithMargins(view, 0, 0) val height = getDecoratedMeasuredHeight(view) val width = getDecoratedMeasuredWidth(view) val top = if (isAppend) offsetY else offsetY - height val bottom = top + height layoutDecoratedWithMargins( view, parentLeft, top, parentLeft + width, bottom) return height } PO-BZPVU$IJMESFO
  14. private fun addRow(position: Int, offsetY: Int, isAppend: Boolean, recycler: Recycler):

    Int { val view = recycler.getViewForPosition(position) addView(view, if (isAppend) -1 else 0) measureChildWithMargins(view, 0, 0) val height = getDecoratedMeasuredHeight(view) val width = getDecoratedMeasuredWidth(view) val top = if (isAppend) offsetY else offsetY - height val bottom = top + height layoutDecoratedWithMargins( view, parentLeft, top, parentLeft + width, bottom) return height } PO-BZPVU$IJMESFO
  15. private fun addRow(position: Int, offsetY: Int, isAppend: Boolean, recycler: Recycler):

    Int { val view = recycler.getViewForPosition(position) addView(view, if (isAppend) -1 else 0) measureChildWithMargins(view, 0, 0) val height = getDecoratedMeasuredHeight(view) val width = getDecoratedMeasuredWidth(view) val top = if (isAppend) offsetY else offsetY - height val bottom = top + height layoutDecoratedWithMargins( view, parentLeft, top, parentLeft + width, bottom) return height } PO-BZPVU$IJMESFO
  16. private fun addRow(position: Int, offsetY: Int, isAppend: Boolean, recycler: Recycler):

    Int { val view = recycler.getViewForPosition(position) addView(view, if (isAppend) -1 else 0) measureChildWithMargins(view, 0, 0) val height = getDecoratedMeasuredHeight(view) val width = getDecoratedMeasuredWidth(view) val top = if (isAppend) offsetY else offsetY - height val bottom = top + height layoutDecoratedWithMargins( view, parentLeft, top, parentLeft + width, bottom) return height } PO-BZPVU$IJMESFO
  17. private fun addRow(position: Int, offsetY: Int, isAppend: Boolean, recycler: Recycler):

    Int { val view = recycler.getViewForPosition(position) addView(view, if (isAppend) -1 else 0) measureChildWithMargins(view, 0, 0) val height = getDecoratedMeasuredHeight(view) val width = getDecoratedMeasuredWidth(view) val top = if (isAppend) offsetY else offsetY - height val bottom = top + height layoutDecoratedWithMargins( view, parentLeft, top, parentLeft + width, bottom) return height } PO-BZPVU$IJMESFO
  18. private fun fillChunk(startPosition: Int, startY: Int, isAppend: Boolean, recycler: Recycler)

    { val remainingSpace = if (isAppend) parentBottom - startY else startY - parentTop var offsetY = startY val range = if (isAppend) startPosition until itemCount else startPosition downTo 0 for (position in range) { val height = addRow(position, offsetY, isAppend, recycler) offsetY += if (isAppend) height else -height val consumed = abs(offsetY - startY) if (consumed > remainingSpace) break } } PO-BZPVU$IJMESFO
  19. private fun fillChunk(startPosition: Int, startY: Int, isAppend: Boolean, recycler: Recycler)

    { val remainingSpace = if (isAppend) parentBottom - startY else startY - parentTop var offsetY = startY val range = if (isAppend) startPosition until itemCount else startPosition downTo 0 for (position in range) { val height = addRow(position, offsetY, isAppend, recycler) offsetY += if (isAppend) height else -height val consumed = abs(offsetY - startY) if (consumed > remainingSpace) break } } PO-BZPVU$IJMESFO
  20. private fun fillChunk(startPosition: Int, startY: Int, isAppend: Boolean, recycler: Recycler)

    { val remainingSpace = if (isAppend) parentBottom - startY else startY - parentTop var offsetY = startY val range = if (isAppend) startPosition until itemCount else startPosition downTo 0 for (position in range) { val height = addRow(position, offsetY, isAppend, recycler) offsetY += if (isAppend) height else -height val consumed = abs(offsetY - startY) if (consumed > remainingSpace) break } } PO-BZPVU$IJMESFO
  21. private fun fillChunk(startPosition: Int, startY: Int, isAppend: Boolean, recycler: Recycler)

    { val remainingSpace = if (isAppend) parentBottom - startY else startY - parentTop var offsetY = startY val range = if (isAppend) startPosition until itemCount else startPosition downTo 0 for (position in range) { val height = addRow(position, offsetY, isAppend, recycler) offsetY += if (isAppend) height else -height val consumed = abs(offsetY - startY) if (consumed > remainingSpace) break } } PO-BZPVU$IJMESFO
  22. override fun onLayoutChildren(recycler: Recycler, state: State) { if (itemCount ==

    0) { detachAndScrapAttachedViews(recycler) return } val restoredFirstVisibleView = getChildAt(0) val restoredPosition = restoredFirstVisibleView?.adapterPosition val restoredTop = restoredFirstVisibleView?.let(this::getDecoratedTop) if (childCount > 0) detachAndScrapAttachedViews(recycler) fillChunk(restoredPosition ?: 0, restoredTop ?: parentTop, isAppend = true, recycler = recycler) } PO-BZPVU$IJMESFO
  23. override fun onLayoutChildren(recycler: Recycler, state: State) { if (itemCount ==

    0) { detachAndScrapAttachedViews(recycler) return } val restoredFirstVisibleView = getChildAt(0) val restoredPosition = restoredFirstVisibleView?.adapterPosition val restoredTop = restoredFirstVisibleView?.let(this::getDecoratedTop) if (childCount > 0) detachAndScrapAttachedViews(recycler) fillChunk(restoredPosition ?: 0, restoredTop ?: parentTop, isAppend = true, recycler = recycler) } PO-BZPVU$IJMESFO
  24. override fun onLayoutChildren(recycler: Recycler, state: State) { if (itemCount ==

    0) { detachAndScrapAttachedViews(recycler) return } val restoredFirstVisibleView = getChildAt(0) val restoredPosition = restoredFirstVisibleView?.adapterPosition val restoredTop = restoredFirstVisibleView?.let(this::getDecoratedTop) if (childCount > 0) detachAndScrapAttachedViews(recycler) fillChunk(restoredPosition ?: 0, restoredTop ?: parentTop, isAppend = true, recycler = recycler) } PO-BZPVU$IJMESFO
  25. override fun onLayoutChildren(recycler: Recycler, state: State) { if (itemCount ==

    0) { detachAndScrapAttachedViews(recycler) return } val restoredFirstVisibleView = getChildAt(0) val restoredPosition = restoredFirstVisibleView?.adapterPosition val restoredTop = restoredFirstVisibleView?.let(this::getDecoratedTop) if (childCount > 0) detachAndScrapAttachedViews(recycler) fillChunk(restoredPosition ?: 0, restoredTop ?: parentTop, isAppend = true, recycler = recycler) } PO-BZPVU$IJMESFO
  26. override fun onSaveInstanceState(): Parcelable? { val firstVisibleItem = getChildAt(0) ?:

    return null return SavedState(firstVisibleItem.adapterPosition, getDecoratedTop(firstVisibleItem)) } override fun onRestoreInstanceState(state: Parcelable?) { savedState = state as? SavedState } PO-BZPVU$IJMESFO
  27. val restoredFirstVisibleView = getChildAt(0) val restoredPosition = savedState?.firstVisibleItemPosition ?: restoredFirstVisibleView?.adapterPosition

    val restoredTop = savedState?.firstVisibleItemTop ?: restoredFirstVisibleView?.let(this::getDecoratedTop) if (childCount > 0) detachAndScrapAttachedViews(recycler) if (restoredPosition != null && restoredTop != null && restoredPosition < itemCount) fillChunk(restoredPosition, restoredTop, isAppend = true, recycler = recycler) else fillChunk(0, parentTop, isAppend = true, recycler = recycler) PO-BZPVU$IJMESFO
  28. private fun calculateActualDy(dy: Int): Int { if (dy == 0)

    return 0 return if (dy > 0) { // up swipe val lastView = getChildAt(childCount - 1) ?: return 0 val bottom = getDecoratedBottom(lastView) if (lastView.adapterPosition == itemCount - 1) if (bottom == parentBottom) 0 else min(bottom - parentBottom, dy) else dy } else { val firstView = getChildAt(0) ?: return 0 val top = getDecoratedTop(firstView) if (firstView.adapterPosition == 0) if (top == parentTop) 0 else max(top - parentTop, dy) else dy } } TDSPMM7FSUJDBMMZ#Z
  29. private fun calculateActualDy(dy: Int): Int { if (dy == 0)

    return 0 return if (dy > 0) { // up swipe val lastView = getChildAt(childCount - 1) ?: return 0 val bottom = getDecoratedBottom(lastView) if (lastView.adapterPosition == itemCount - 1) if (bottom == parentBottom) 0 else min(bottom - parentBottom, dy) else dy } else { val firstView = getChildAt(0) ?: return 0 val top = getDecoratedTop(firstView) if (firstView.adapterPosition == 0) if (top == parentTop) 0 else max(top - parentTop, dy) else dy } } TDSPMM7FSUJDBMMZ#Z
  30. private fun calculateActualDy(dy: Int): Int { if (dy == 0)

    return 0 return if (dy > 0) { // up swipe val lastView = getChildAt(childCount - 1) ?: return 0 val bottom = getDecoratedBottom(lastView) if (lastView.adapterPosition == itemCount - 1) if (bottom == parentBottom) 0 else min(bottom - parentBottom, dy) else dy } else { val firstView = getChildAt(0) ?: return 0 val top = getDecoratedTop(firstView) if (firstView.adapterPosition == 0) if (top == parentTop) 0 else max(top - parentTop, dy) else dy } } TDSPMM7FSUJDBMMZ#Z
  31. private fun calculateActualDy(dy: Int): Int { if (dy == 0)

    return 0 return if (dy > 0) { // up swipe val lastView = getChildAt(childCount - 1) ?: return 0 val bottom = getDecoratedBottom(lastView) if (lastView.adapterPosition == itemCount - 1) if (bottom == parentBottom) 0 else min(bottom - parentBottom, dy) else dy } else { val firstView = getChildAt(0) ?: return 0 val top = getDecoratedTop(firstView) if (firstView.adapterPosition == 0) if (top == parentTop) 0 else max(top - parentTop, dy) else dy } } TDSPMM7FSUJDBMMZ#Z
  32. private fun recycleTop(recycler: Recycler) { children.forEach { if (getDecoratedBottom(it) <

    parentTop) removeAndRecycleView(it, recycler) else return } } TDSPMM7FSUJDBMMZ#Z
  33. private fun recycleTop(recycler: Recycler) { children.forEach { if (getDecoratedBottom(it) <

    parentTop) removeAndRecycleView(it, recycler) else return } } TDSPMM7FSUJDBMMZ#Z
  34. private fun recycleTop(recycler: Recycler) { children.forEach { if (getDecoratedBottom(it) <

    parentTop) removeAndRecycleView(it, recycler) else return } } TDSPMM7FSUJDBMMZ#Z
  35. override fun scrollVerticallyBy(dy: Int, recycler: Recycler, state: State): Int {

    val actualDy = calculateActualDy(dy) if (actualDy == 0) return 0 offsetChildrenVertical(-actualDy) if (actualDy > 0) { recycleTop(recycler) val lastView = getChildAt(childCount - 1) ?: return 0 val bottom = getDecoratedBottom(lastView) if (bottom < parentBottom) fillChunk(lastView.adapterPosition + 1, bottom, true, recycler) } else { … } return actualDy } TDSPMM7FSUJDBMMZ#Z
  36. override fun scrollVerticallyBy(dy: Int, recycler: Recycler, state: State): Int {

    val actualDy = calculateActualDy(dy) if (actualDy == 0) return 0 offsetChildrenVertical(-actualDy) if (actualDy > 0) { recycleTop(recycler) val lastView = getChildAt(childCount - 1) ?: return 0 val bottom = getDecoratedBottom(lastView) if (bottom < parentBottom) fillChunk(lastView.adapterPosition + 1, bottom, true, recycler) } else { … } return actualDy } TDSPMM7FSUJDBMMZ#Z
  37. override fun scrollVerticallyBy(dy: Int, recycler: Recycler, state: State): Int {

    val actualDy = calculateActualDy(dy) if (actualDy == 0) return 0 offsetChildrenVertical(-actualDy) if (actualDy > 0) { recycleTop(recycler) val lastView = getChildAt(childCount - 1) ?: return 0 val bottom = getDecoratedBottom(lastView) if (bottom < parentBottom) fillChunk(lastView.adapterPosition + 1, bottom, true, recycler) } else { … } return actualDy } TDSPMM7FSUJDBMMZ#Z
  38. override fun scrollVerticallyBy(dy: Int, recycler: Recycler, state: State): Int {

    val actualDy = calculateActualDy(dy) if (actualDy == 0) return 0 offsetChildrenVertical(-actualDy) if (actualDy > 0) { recycleTop(recycler) val lastView = getChildAt(childCount - 1) ?: return 0 val bottom = getDecoratedBottom(lastView) if (bottom < parentBottom) fillChunk(lastView.adapterPosition + 1, bottom, true, recycler) } else { … } return actualDy } TDSPMM7FSUJDBMMZ#Z
  39. override fun scrollVerticallyBy(dy: Int, recycler: Recycler, state: State): Int {

    val actualDy = calculateActualDy(dy) if (actualDy == 0) return 0 offsetChildrenVertical(-actualDy) if (actualDy > 0) { recycleTop(recycler) val lastView = getChildAt(childCount - 1) ?: return 0 val bottom = getDecoratedBottom(lastView) if (bottom < parentBottom) fillChunk(lastView.adapterPosition + 1, bottom, true, recycler) } else { … } return actualDy } TDSPMM7FSUJDBMMZ#Z
  40. override fun scrollVerticallyBy(dy: Int, recycler: Recycler, state: State): Int {

    val actualDy = calculateActualDy(dy) if (actualDy == 0) return 0 offsetChildrenVertical(-actualDy) if (actualDy > 0) { recycleTop(recycler) val lastView = getChildAt(childCount - 1) ?: return 0 val bottom = getDecoratedBottom(lastView) if (bottom < parentBottom) fillChunk(lastView.adapterPosition + 1, bottom, true, recycler) } else { … } return actualDy } TDSPMM7FSUJDBMMZ#Z
  41. override fun onLayoutChildren(recycler: Recycler, state: State) { … if (pendingScrollPosition

    != RecyclerView.NO_POSITION) { fillChunk(pendingScrollPosition, parentTop, true, recycler) val lastVisibleView = getChildAt(childCount - 1) ?: return val bottom = getDecoratedBottom(lastVisibleView) if (lastVisibleView.adapterPosition.isLast && bottom < parentBottom) fixLayoutGap() return } … } TDSPMM5P1PTJUJPO
  42. override fun onLayoutChildren(recycler: Recycler, state: State) { … if (pendingScrollPosition

    != RecyclerView.NO_POSITION) { fillChunk(pendingScrollPosition, parentTop, true, recycler) val lastVisibleView = getChildAt(childCount - 1) ?: return val bottom = getDecoratedBottom(lastVisibleView) if (lastVisibleView.adapterPosition.isLast && bottom < parentBottom) fixLayoutGap() return } … } TDSPMM5P1PTJUJPO
  43. override fun onLayoutChildren(recycler: Recycler, state: State) { … if (pendingScrollPosition

    != RecyclerView.NO_POSITION) { fillChunk(pendingScrollPosition, parentTop, true, recycler) val lastVisibleView = getChildAt(childCount - 1) ?: return val bottom = getDecoratedBottom(lastVisibleView) if (lastVisibleView.adapterPosition.isLast && bottom < parentBottom) fixLayoutGap() return } … } TDSPMM5P1PTJUJPO 99
  44. override fun onLayoutChildren(recycler: Recycler, state: State) { … if (pendingScrollPosition

    != RecyclerView.NO_POSITION) { fillChunk(pendingScrollPosition, parentTop, true, recycler) val lastVisibleView = getChildAt(childCount - 1) ?: return val bottom = getDecoratedBottom(lastVisibleView) if (lastVisibleView.adapterPosition.isLast && bottom < parentBottom) fixLayoutGap() return } … } TDSPMM5P1PTJUJPO 99
  45. override fun onLayoutChildren(recycler: Recycler, state: State) { … if (pendingScrollPosition

    != RecyclerView.NO_POSITION) { fillChunk(pendingScrollPosition, parentTop, true, recycler) val lastVisibleView = getChildAt(childCount - 1) ?: return val bottom = getDecoratedBottom(lastVisibleView) if (lastVisibleView.adapterPosition.isLast && bottom < parentBottom) fixLayoutGap() return } … } TDSPMM5P1PTJUJPO 99 98 97 96 95