How to implement TimetablelLayoutManager

How to implement TimetablelLayoutManager

5f533179da1c82722252cbcb93e7356f?s=128

Moyuru Aizawa

March 06, 2019
Tweet

Transcript

  1. 10.

    ‣ "EBQUFS ‣ -BZPVU.BOBHFS ‣ *UFN%FDPSBUJPO ‣ *UFN"OJNBUPS ‣ *UFN5PVDI)FMQFS

    ‣ 4OBQ)FMQFS ‣ 3FDZDMFE7JFX1PPM ‣ %JGG6UJM 3FDZDMFS7JFXͱ͸
  2. 15.

    ‣ 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. 16.

    ‣ 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. 17.

    ‣ 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. 18.

    ‣ 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. 19.

    ‣ 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. 20.

    ‣ 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. 21.

    ‣ 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 ‣ ʜ 5JNFUBCMF-BZPVU͕࣮૷͍ͯ͠Δؔ਺ରԠ͍ͯ͠Δػೳ
  9. 22.

    ‣ 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 ‣ ʜ 5JNFUBCMF-BZPVUʹ࣮૷༧ఆͷ΋ͷ ༏ઌ౓த
  10. 23.

    ‣ 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 ‣ ʜ 5JNFUBCMF-BZPVUʹ࣮૷༧ఆͷ΋ͷ ༏ઌ౓௿
  11. 26.

    ‣ PO-BZPVU$IJMESFO ‣ QFSJPETͷ৘ใऩू ‣ JOJUJBMMBZPVU ‣ TDSPMM7FSUJDBMMZ#ZTDSPMM)PSJ[POUBMMZ#Z ‣ DIJMEWJFXTͷҠಈ

    ‣ ݟ͑ͳ͘ͳͬͨDIJMEWJFXΛSFNPWF ‣ ۭ͖εϖʔεʹDIJMEWJFXΛBEE -BZPVU.BOBHFS͕΍͍ͬͯΔ͜ͱ ͬ͘͟Γ
  12. 39.

    (0 until itemCount).forEach { val periodInfo = periodLookUp(it) val column

    = columns.getOrPut(periodInfo.columnNumber) { ArrayList() } val period = Period( TimeUnit.MILLISECONDS.toMinutes(periodInfo.startUnixMillis).toInt(), TimeUnit.MILLISECONDS.toMinutes(periodInfo.endUnixMillis).toInt(), periodInfo.columnNumber, adapterPosition = it, positionInColumn = column.size ) periods.add(period) column.add(period) if (it == 0) { firstStartUnixMin = period.startUnixMin lastEndUnixMin = period.endUnixMin } else { firstStartUnixMin = min(period.startUnixMin, firstStartUnixMin) lastEndUnixMin = max(period.endUnixMin, lastEndUnixMin) } } ֤QFSJPEͷ৘ใऩू
  13. 40.

    (0 until itemCount).forEach { val periodInfo = periodLookUp(it) val column

    = columns.getOrPut(periodInfo.columnNumber) { ArrayList() } val period = Period( TimeUnit.MILLISECONDS.toMinutes(periodInfo.startUnixMillis).toInt(), TimeUnit.MILLISECONDS.toMinutes(periodInfo.endUnixMillis).toInt(), periodInfo.columnNumber, adapterPosition = it, positionInColumn = column.size ) periods.add(period) column.add(period) if (it == 0) { firstStartUnixMin = period.startUnixMin lastEndUnixMin = period.endUnixMin } else { firstStartUnixMin = min(period.startUnixMin, firstStartUnixMin) lastEndUnixMin = max(period.endUnixMin, lastEndUnixMin) } } ֤QFSJPEͷ৘ใऩू
  14. 41.

    (0 until itemCount).forEach { val periodInfo = periodLookUp(it) val column

    = columns.getOrPut(periodInfo.columnNumber) { ArrayList() } val period = Period( TimeUnit.MILLISECONDS.toMinutes(periodInfo.startUnixMillis).toInt(), TimeUnit.MILLISECONDS.toMinutes(periodInfo.endUnixMillis).toInt(), periodInfo.columnNumber, adapterPosition = it, positionInColumn = column.size ) periods.add(period) column.add(period) if (it == 0) { firstStartUnixMin = period.startUnixMin lastEndUnixMin = period.endUnixMin } else { firstStartUnixMin = min(period.startUnixMin, firstStartUnixMin) lastEndUnixMin = max(period.endUnixMin, lastEndUnixMin) } } ֤QFSJPEͷ৘ใऩू
  15. 42.

    anchor.leftColumn = 0 val columnCount = columns.size() val offsetY =

    parentTop var offsetX = parentLeft for (columnNumber in 0 until columnCount) { offsetX += addColumn( columns[columnNumber].first(), offsetX, offsetY, true, recycler) anchor.rightColumn = columnNumber if (offsetX > parentRight) break } *OJUJBMMBZPVU
  16. 43.

    val range = startPeriod.positionInColumn until column.size for (i in range)

    { val period = column[i] val (width, height) = addPeriod(period, direction, offsetX, offsetY, recycler) offsetY += height columnWidth = width if (i == startPeriod.positionInColumn) anchor.top.put(columnNum, period.adapterPosition) anchor.bottom.put(columnNum, period.adapterPosition) if (offsetY > parentBottom) break } *OJUJBMMBZPVU
  17. 44.

    val range = startPeriod.positionInColumn until column.size for (i in range)

    { val period = column[i] val (width, height) = addPeriod(period, direction, offsetX, offsetY, recycler) offsetY += height columnWidth = width if (i == startPeriod.positionInColumn) anchor.top.put(columnNum, period.adapterPosition) anchor.bottom.put(columnNum, period.adapterPosition) if (offsetY > parentBottom) break } *OJUJBMMBZPVU
  18. 45.

    anchor.leftColumn = 0 val columnCount = columns.size() val offsetY =

    parentTop var offsetX = parentLeft for (columnNumber in 0 until columnCount) { offsetX += addColumn( columns[columnNumber].first(), offsetX, offsetY, true, recycler) anchor.rightColumn = columnNumber if (offsetX > parentRight) break } *OJUJBMMBZPVU
  19. 47.

    val bottomView = findBottomView() ?: return 0 val period =

    periods.getOrNull(bottomView.adapterPosition) ?: return 0 val bottom = getDecoratedBottom(bottomView) if (period.endUnixMin == lastEndUnixMin) if (bottom == parentBottom) 0 else min(dy, bottom - parentBottom) else dy εΫϩʔϧྔͷܭࢉ
  20. 48.

    val bottomView = findBottomView() ?: return 0 val period =

    periods.getOrNull(bottomView.adapterPosition) ?: return 0 val bottom = getDecoratedBottom(bottomView) if (period.endUnixMin == lastEndUnixMin) if (bottom == parentBottom) 0 else min(dy, bottom - parentBottom) else dy εΫϩʔϧྔͷܭࢉ
  21. 49.

    val bottomView = findBottomView() ?: return 0 val period =

    periods.getOrNull(bottomView.adapterPosition) ?: return 0 val bottom = getDecoratedBottom(bottomView) if (period.endUnixMin == lastEndUnixMin) if (bottom == parentBottom) 0 else min(dy, bottom - parentBottom) else dy εΫϩʔϧྔͷܭࢉ
  22. 50.

    val bottomView = findBottomView() ?: return 0 val period =

    periods.getOrNull(bottomView.adapterPosition) ?: return 0 val bottom = getDecoratedBottom(bottomView) if (period.endUnixMin == lastEndUnixMin) if (bottom == parentBottom) 0 else min(dy, bottom - parentBottom) else dy εΫϩʔϧྔͷܭࢉ
  23. 51.

    override fun scrollVerticallyBy( dy: Int, recycler: Recycler, state: State ):

    Int { if (dy == 0) return 0 val actualDy = calculateVerticallyScrollAmount(dy) if (actualDy == 0) return 0 offsetChildrenVertical(-actualDy) … } $IJMEWJFXTͷҠಈ
  24. 52.

    override fun scrollVerticallyBy( dy: Int, recycler: Recycler, state: State ):

    Int { if (dy == 0) return 0 val actualDy = calculateVerticallyScrollAmount(dy) if (actualDy == 0) return 0 offsetChildrenVertical(-actualDy) … } $IJMEWJFXTͷҠಈ
  25. 53.

    (anchor.leftColumn..anchor.rightColumn) .forEach { columnNum -> val column = columns[columnNum] val

    top = periods[anchor.top[columnNum]] val bottom = periods[anchor.bottom[columnNum]] column.subList( top.positionInColumn, bottom.positionInColumn ).forEach { val view = findViewByPosition(it.adapterPosition)?: return if (getDecoratedBottom(view) >= parentTop) return removeAndRecycleView(view, recycler) val belowPosition = column[it.positionInColumn + 1] .adapterPosition anchor.top.put(columnNum, belowPosition) } } ը໘͔ΒͰͨDIJMEWJFXͷ࡟আ
  26. 54.

    (anchor.leftColumn..anchor.rightColumn) .forEach { columnNum -> val column = columns[columnNum] val

    top = periods[anchor.top[columnNum]] val bottom = periods[anchor.bottom[columnNum]] column.subList( top.positionInColumn, bottom.positionInColumn ).forEach { val view = findViewByPosition(it.adapterPosition)?: return if (getDecoratedBottom(view) >= parentTop) return removeAndRecycleView(view, recycler) val belowPosition = column[it.positionInColumn + 1] .adapterPosition anchor.top.put(columnNum, belowPosition) } } ը໘͔ΒͰͨDIJMEWJFXͷ࡟আ
  27. 55.

    (anchor.leftColumn..anchor.rightColumn) .forEach { columnNum -> val column = columns[columnNum] val

    top = periods[anchor.top[columnNum]] val bottom = periods[anchor.bottom[columnNum]] column.subList( top.positionInColumn, bottom.positionInColumn ).forEach { val view = findViewByPosition(it.adapterPosition)?: return if (getDecoratedBottom(view) >= parentTop) return removeAndRecycleView(view, recycler) val belowPosition = column[it.positionInColumn + 1] .adapterPosition anchor.top.put(columnNum, belowPosition) } } ը໘͔ΒͰͨDIJMEWJFXͷ࡟আ
  28. 56.

    (anchor.leftColumn..anchor.rightColumn) .forEach { columnNum -> val column = columns[columnNum] val

    top = periods[anchor.top[columnNum]] val bottom = periods[anchor.bottom[columnNum]] column.subList( top.positionInColumn, bottom.positionInColumn ).forEach { val view = findViewByPosition(it.adapterPosition)?: return if (getDecoratedBottom(view) >= parentTop) return removeAndRecycleView(view, recycler) val belowPosition = column[it.positionInColumn + 1] .adapterPosition anchor.top.put(columnNum, belowPosition) } } ը໘͔ΒͰͨDIJMEWJFXͷ࡟আ
  29. 57.

    (anchor.leftColumn..anchor.rightColumn) .forEach { columnNum -> val column = columns[columnNum] val

    top = periods[anchor.top[columnNum]] val bottom = periods[anchor.bottom[columnNum]] column.subList( top.positionInColumn, bottom.positionInColumn ).forEach { val view = findViewByPosition(it.adapterPosition)?: return if (getDecoratedBottom(view) >= parentTop) return removeAndRecycleView(view, recycler) val belowPosition = column[it.positionInColumn + 1] .adapterPosition anchor.top.put(columnNum, belowPosition) } } ը໘͔ΒͰͨDIJMEWJFXͷ࡟আ
  30. 58.

    anchor.bottom.forEach { columnNum, position -> val view = findViewByPosition(position) ?:

    return@forEach val bottom = getDecoratedBottom(view) if (bottom < parentBottom) { val left = getDecoratedLeft(view) val period = periods.getOrNull(position) ?: return@forEach val nextPeriod = columns.get(columnNum) .getOrNull(period.positionInColumn + 1) ?: return@forEach addPeriodsToColumn(nextPeriod, left, bottom, true, recycler) } } ۭ͖εϖʔεʹWJFXΛ௥Ճ
  31. 59.

    anchor.bottom.forEach { columnNum, position -> val view = findViewByPosition(position) ?:

    return@forEach val bottom = getDecoratedBottom(view) if (bottom < parentBottom) { val left = getDecoratedLeft(view) val period = periods.getOrNull(position) ?: return@forEach val nextPeriod = columns.get(columnNum) .getOrNull(period.positionInColumn + 1) ?: return@forEach addPeriodsToColumn(nextPeriod, left, bottom, true, recycler) } } ۭ͖εϖʔεʹWJFXΛ௥Ճ
  32. 60.

    anchor.bottom.forEach { columnNum, position -> val view = findViewByPosition(position) ?:

    return@forEach val bottom = getDecoratedBottom(view) if (bottom < parentBottom) { val left = getDecoratedLeft(view) val period = periods.getOrNull(position) ?: return@forEach val nextPeriod = columns.get(columnNum) .getOrNull(period.positionInColumn + 1) ?: return@forEach addPeriodsToColumn(nextPeriod, left, bottom, true, recycler) } } ۭ͖εϖʔεʹWJFXΛ௥Ճ
  33. 61.

    anchor.bottom.forEach { columnNum, position -> val view = findViewByPosition(position) ?:

    return@forEach val bottom = getDecoratedBottom(view) if (bottom < parentBottom) { val left = getDecoratedLeft(view) val period = periods.getOrNull(position) ?: return@forEach val nextPeriod = columns.get(columnNum) .getOrNull(period.positionInColumn + 1) ?: return@forEach addPeriodsToColumn(nextPeriod, left, bottom, true, recycler) } } ۭ͖εϖʔεʹWJFXΛ௥Ճ
  34. 63.