How to implement TimetableLayout ver.2

How to implement TimetableLayout ver.2

5f533179da1c82722252cbcb93e7356f?s=128

Moyuru Aizawa

March 26, 2019
Tweet

Transcript

  1. ͳΜͱ͔KaigiͷTimetable @MoyuruAizawa

  2. MoyuruAizawa Moyuru Aizawa
 Software engineer of CATS Div. CyberAgent Inc.

    
 Previously at Pairs Div. Eureka Inc.
  3. ˙˙˙˙DPOGFSFODFBQQ ˙˙˙˙

  4. -BZPVU.BOBHFSͱ͸

  5. ‣ 3FDZDMFS7JFXͷDIJMEWJFXTͷϨΠΞ΢τΛ୲౰͢ΔϞδϡʔϧ ‣ -BZPVU.BOBHFSΛม͑Δ͜ͱͰ༷ʑͳϨΠΞ΢τΛ࣮ݱ͢Δࣄ͕Ͱ͖ Δ -BZPVU.BOBHFSͱ͸

  6. -BZPVU.BOBHFSͱ͸ -JOFBS-BZPVU.BOBHFS (SJE-BZPVU.BOBHFS 4UBHHFSFE(SJE-BZPVU.BOBHFS 'MFYCPY-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. ‣ 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ͷؔ਺ػೳ
  9. ‣ ϨΠΞ΢τͷॳظԽ ‣ BEBQUFSDIBOHFT ‣ SFRVFTU-BZPVU PO-BZPVU$IJMESFO

  10. PO-BZPVU$IJMESFO LayoutManager Recycler

  11. PO-BZPVU$IJMESFO LayoutManager Recycler 3FDZDMFSΛ࢖ͬͯͲ͔͔͜Β7JFXΛҾͬுͬͯ͘Δ

  12. Recycler Scrap Heap PO-BZPVU$IJMESFO LayoutManager View View View 3FDZDMFS͕͍࣋ͬͯΔTDSBQFEWJFX

  13. Recycler Scrap Heap PO-BZPVU$IJMESFO LayoutManager View View View 3FDZDMFS͕͍࣋ͬͯΔTDSBQFEWJFX

  14. PO-BZPVU$IJMESFO LayoutManager Recycler Recycled ViewPool View View View 3FDZDMFE7JFX1PPM͕͍࣋ͬͯΔSFDZDMFEWJFX

  15. PO-BZPVU$IJMESFO LayoutManager Recycler Recycled ViewPool View View View 3FDZDMFE7JFX1PPM͕͍࣋ͬͯΔSFDZDMFEWJFX

  16. PO-BZPVU$IJMESFO LayoutManager Recycler Adapter "EBQUFSܦ༝Ͱ7JFXΛJOqBUF

  17. PO-BZPVU$IJMESFO LayoutManager Recycler Adapter View "EBQUFSܦ༝Ͱ7JFXΛJOqBUF

  18. PO-BZPVU$IJMESFO LayoutManager Recycler Adapter View "EBQUFSܦ༝Ͱ7JFXΛJOqBUF

  19. PO-BZPVU$IJMESFO LayoutManager View "EEWJFX

  20. PO-BZPVU$IJMESFO LayoutManager View .FBTVSF

  21. PO-BZPVU$IJMESFO LayoutManager View -BZPVU

  22. PO-BZPVU$IJMESFO 3FDZDMFS͔Β7JFXΛ΋Β͏
 7JFXΛBEE NFBTVSF MBZPVU ͜ͷҰ࿈ͷ࡞ۀΛ3FDZDMFS7JFX͕DIJMEWJFXTͰຬͨ͞ΕΔ·Ͱߦ͏ LayoutManager Recycler View

  23. PO-BZPVU$IJMESFO LayoutManager Recycler View 3FDZDMFS͔Β7JFXΛ΋Β͏
 7JFXΛBEE NFBTVSF MBZPVU ͜ͷҰ࿈ͷ࡞ۀΛ3FDZDMFS7JFX͕DIJMEWJFXTͰຬͨ͞ΕΔ·Ͱߦ͏

  24. PO-BZPVU$IJMESFO LayoutManager View "EEWJFX
 .FBTVSF
 -BZPVU 3FDZDMFS͔Β7JFXΛ΋Β͏
 7JFXΛBEE NFBTVSF MBZPVU

    ͜ͷҰ࿈ͷ࡞ۀΛ3FDZDMFS7JFX͕DIJMEWJFXTͰຬͨ͞ΕΔ·Ͱߦ͏
  25. 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
  26. 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
  27. 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
  28. 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
  29. 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
  30. override fun onLayoutChildren(recycler: Recycler, state: State) { var offsetY =

    parentTop for (position in 0 until itemCount) { offsetY += addRow(position, offsetY, isAppend, recycler) if (offsetY > parentBottom) break } } PO-BZPVU$IJMESFO
  31. override fun onLayoutChildren(recycler: Recycler, state: State) { var offsetY =

    parentTop for (position in 0 until itemCount) { offsetY += addRow(position, offsetY, isAppend, recycler) if (offsetY > parentBottom) break } } PO-BZPVU$IJMESFO
  32. override fun onLayoutChildren(recycler: Recycler, state: State) { var offsetY =

    parentTop for (position in 0 until itemCount) { offsetY += addRow(position, offsetY, isAppend, recycler) if (offsetY > parentBottom) break } } PO-BZPVU$IJMESFO
  33. override fun onLayoutChildren(recycler: Recycler, state: State) { var offsetY =

    parentTop for (position in 0 until itemCount) { offsetY += addRow(position, offsetY, isAppend, recycler) if (offsetY > parentBottom) break } } PO-BZPVU$IJMESFO
  34. ‣ DIJMEWJFXTͷεϥΠυ ‣ ը໘͔Βग़ͨDIJMEWJFXTͷSFNPWF ‣ ۭ͖εϖʔεʹDIJMEWJFXTͷBEE TDSPMM7FSUJDBMMZ#Z

  35. ‣ DIJMEWJFXTͷεϥΠυ ‣ ը໘͔Βग़ͨDIJMEWJFXTͷSFNPWF ‣ ۭ͖εϖʔεʹDIJMEWJFXTͷBEE TDSPMM7FSUJDBMMZ#Z

  36. ‣ DIJMEWJFXTͷεϥΠυ ‣ ը໘͔Βग़ͨDIJMEWJFXTͷSFNPWF ‣ ۭ͖εϖʔεʹDIJMEWJFXTͷBEE TDSPMM7FSUJDBMMZ#Z

  37. ‣ DIJMEWJFXTͷεϥΠυ ‣ ը໘͔Βग़ͨDIJMEWJFXTͷSFNPWF ‣ ۭ͖εϖʔεʹDIJMEWJFXTͷBEE TDSPMM7FSUJDBMMZ#Z

  38. TDSPMM7FSUJDBMMZ#Z

  39. TDSPMM7FSUJDBMMZ#Z

  40. TDSPMM7FSUJDBMMZ#Z

  41. TDSPMM7FSUJDBMMZ#Z

  42. TDSPMM7FSUJDBMMZ#Z

  43. TDSPMM7FSUJDBMMZ#Z if (bottom < parentTop)

  44. TDSPMM7FSUJDBMMZ#Z if (bottom < parentTop)

  45. TDSPMM7FSUJDBMMZ#Z if (bottom < parentTop)

  46. TDSPMM7FSUJDBMMZ#Z if (bottom < parentBottom)

  47. TDSPMM7FSUJDBMMZ#Z if (bottom < parentBottom)

  48. TDSPMM7FSUJDBMMZ#Z if (bottom < parentBottom)

  49. TDSPMM7FSUJDBMMZ#Z if (bottom < parentBottom)

  50. TDSPMM7FSUJDBMMZ#Z if (bottom < parentBottom)

  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) if (actualDy > 0) { … } else { … } return actualDy } TDSPMM7FSUJDBMMZ#Z
  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) if (actualDy > 0) { … } else { … } return actualDy } TDSPMM7FSUJDBMMZ#Z
  53. 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) if (actualDy > 0) { … } else { … } return actualDy } TDSPMM7FSUJDBMMZ#Z
  54. 5JNFUBCMF-BZPVU.BOBHFSͷ࣮૷

  55. ‣ -JOFBS-BZPVU.BOBHFS ‣ "EBQUFSͷΞΠςϜॱ7JFXͷϨΠΞ΢τॱ ‣ 7JFXͷߴ͞7JFXʹ͓·͔ͤ ‣ 5JNFUBCMF-BZPVU.BOBHFS ‣ "EBQUFSͷΞΠςϜॱʺ7JFXͷϨΠΞ΢τॱ

    ‣ ਖ਼͍͠ॱংͰϨΠΞ΢τ͢Δʹ͸ɺ
 ΧϥϜ൪߸ ϧʔϜ൪߸ ͱ։࢝࣌ؒʹΑͬͯ
 ϨΠΞ΢τ͢΂͖ΞΠςϜͷQPTJUJPOΛࢉग़͢Δඞཁ͕͋Δ ‣ 7JFXͷߴ͞ηογϣϯͷ௕͞ 5JNFUBCMF-BZPVU.BOBHFSͷ࣮૷
  56. ‣ -JOFBS-BZPVU.BOBHFS ‣ "EBQUFSͷΞΠςϜॱ7JFXͷϨΠΞ΢τॱ ‣ 7JFXͷߴ͞7JFXʹ͓·͔ͤ ‣ 5JNFUBCMF-BZPVU.BOBHFS ‣ "EBQUFSͷΞΠςϜॱʺ7JFXͷϨΠΞ΢τॱ

    ‣ ਖ਼͍͠ॱংͰϨΠΞ΢τ͢Δʹ͸ɺ
 ΧϥϜ൪߸ ϧʔϜ൪߸ ͱ։࢝࣌ؒʹΑͬͯ
 ϨΠΞ΢τ͢΂͖ΞΠςϜͷQPTJUJPOΛࢉग़͢Δඞཁ͕͋Δ ‣ 7JFXͷߴ͞ηογϣϯͷ௕͞ 5JNFUBCMF-BZPVU.BOBHFSͷ࣮૷
  57. ‣ -JOFBS-BZPVU.BOBHFS ‣ "EBQUFSͷΞΠςϜॱ7JFXͷϨΠΞ΢τॱ ‣ 7JFXͷߴ͞7JFXʹ͓·͔ͤ ‣ 5JNFUBCMF-BZPVU.BOBHFS ‣ "EBQUFSͷΞΠςϜॱʺ7JFXͷϨΠΞ΢τॱ

    ‣ ਖ਼͍͠ॱংͰϨΠΞ΢τ͢Δʹ͸ɺ
 ΧϥϜ൪߸ ϧʔϜ൪߸ ͱ։࢝࣌ؒʹΑͬͯ
 ϨΠΞ΢τ͢΂͖ΞΠςϜͷQPTJUJPOΛࢉग़͢Δඞཁ͕͋Δ ‣ 7JFXͷߴ͞ηογϣϯͷ௕͞ 5JNFUBCMF-BZPVU.BOBHFSͷ࣮૷
  58. ‣ -JOFBS-BZPVU.BOBHFS ‣ "EBQUFSͷΞΠςϜॱ7JFXͷϨΠΞ΢τॱ ‣ 7JFXͷߴ͞7JFXʹ͓·͔ͤ ‣ 5JNFUBCMF-BZPVU.BOBHFS ‣ "EBQUFSͷΞΠςϜॱʺ7JFXͷϨΠΞ΢τॱ

    ‣ ਖ਼͍͠ॱংͰϨΠΞ΢τ͢Δʹ͸ɺ
 ΧϥϜ൪߸ ϧʔϜ൪߸ ͱ։࢝࣌ؒʹΑͬͯ
 ϨΠΞ΢τ͢΂͖ΞΠςϜͷQPTJUJPOΛࢉग़͢Δඞཁ͕͋Δ ‣ 7JFXͷߴ͞ηογϣϯͷ௕͞ 5JNFUBCMF-BZPVU.BOBHFSͷ࣮૷
  59. private data class Period( val startUnixMin: Int, val endUnixMin: Int,

    val columnNumber: Int, val adapterPosition: Int, val positionInColumn: Int ) { val durationMin = endUnixMin - startUnixMin } 5JNFUBCMF-BZPVU.BOBHFSͷ࣮૷ ֤1FSJPEͷ৘ใΛ༧Ίऩू͓ͯ͘͠
  60. PO-BZPVU$IJMESFO … Period 0 Period 1 Period 2 Period 3

    Period 4 Period 5 Period 6 Period 7 Period 8 Period 0 Period 1 Period 2 Period 3 Period 4 Period 5 Period 6 Period 7 Period 8
  61. PO-BZPVU$IJMESFO … Period 0 Period 1 Period 2 Period 3

    Period 4 Period 5 Period 6 Period 7 Period 8 Column 0 Column 1 Column 2 -JTUɺ$PMVNO/VNCFSͷ.BQͰͱ͓ͬͯ͘ … … … Period 0 Period 1 Period 2 Period 4 Period 6 Period 5 Period 3 Period 8 Period 7
  62. PO-BZPVU$IJMESFO … Period 0 Period 1 Period 2 Period 3

    Period 4 Period 5 Period 6 Period 7 Period 8 Column 0 Column 1 Column 2 … … … Period 0 Period 1 Period 2 Period 4 Period 6 Period 5 Period 3 Period 8 Period 7 Period 0 Period 1 Period 2 Period 4 Period 6 Period 5 Period 3 Period 8 Period 7
  63. PO-BZPVU$IJMESFO … Period 0 Period 1 Period 2 Period 3

    Period 4 Period 5 Period 6 Period 7 Period 8 Period 0 Period 1 Period 2 Period 4 Period 6 Period 5 Period 3 Period 8 Period 7 Column 0 Column 1 Column 2 Period 0 Period 1 Period 2 Period 4 Period 6 Period 5 Period 3 Period 8 Period 7 … … …
  64. TDSPMM7FSUJDBMMZ#Z Period 0 Period 1 Period 2 Period 4 Period

    6 Period 5 Period 3 Period 8 Period 7
  65. TDSPMM7FSUJDBMMZ#Z Period 0 Period 1 Period 2 Period 4 Period

    6 Period 5 Period 3 Period 8 Period 7
  66. TDSPMM7FSUJDBMMZ#Z .BQ͔Β$PMVNOͷ-JTUΛͱͬͯ࣍ͷ1FSJPEΛ௥Ճ͍ͯ͘͠ Period 0 Period 1 Period 2 Period 4

    Period 6 Period 5 Period 3 Period 8 Period 7 Period 11
  67. TDSPMM7FSUJDBMMZ#Z Period 0 Period 1 Period 2 Period 4 Period

    6 Period 5 Period 3 Period 8 Period 7 Period 9 Period 11 .BQ͔Β$PMVNOͷ-JTUΛͱͬͯ࣍ͷ1FSJPEΛ௥Ճ͍ͯ͘͠
  68. TDSPMM7FSUJDBMMZ#Z Period 0 Period 1 Period 2 Period 4 Period

    6 Period 5 Period 3 Period 8 Period 7 Period 9 Period 10 Period 11 .BQ͔Β$PMVNOͷ-JTUΛͱͬͯ࣍ͷ1FSJPEΛ௥Ճ͍ͯ͘͠
  69. TDSPMM)PSJ[POUBMMZ#Z Period 0 Period 1 Period 2 Period 4 Period

    6 Period 5 Period 3 Period 8 Period 7 Period 9 Period 10 Period 11
  70. TDSPMM)PSJ[POUBMMZ#Z Period 0 Period 1 Period 2 Period 4 Period

    6 Period 5 Period 3 Period 8 Period 7 Period 9 Period 10 Period 11 ࣍ͷΧϥϜͷҰ൪࠷ॳʹඳը͢΂͖1FSJPEΛࢉग़͢Δ
  71. TDSPMM)PSJ[POUBMMZ#Z Period 0 Period 1 Period 2 Period 4 Period

    6 Period 5 Period 3 Period 8 Period 7 Period 9 Period 10 Period 11 $PMVNOͷத͔Β.JOJNVN4UBSU"UҎ্.BY&OE"UҎԼͷ1FSJPEΛ୳͢ .JOJNVN4UBSU"U .BY&OE"U
  72. TDSPMM)PSJ[POUBMMZ#Z Period 0 Period 1 Period 2 Period 4 Period

    6 Period 5 Period 3 Period 8 Period 7 Period 9 Period 10 Period 11 Period 12 $PMVNOͷத͔Β.JOJNVN4UBSU"UҎ্.BY&OE"UҎԼͷ1FSJPEΛ୳͢ .JOJNVN4UBSU"U .BY&OE"U
  73. ͻͨ͢ΒੵΈ໦Λ͍ͯ͘͠࡞ۀ

  74. ‣ IUUQTTQFBLFSEFDLDPNMWMBIPXUPJNQMFNFOU UJNFUBCMFMMBZPVUNBOBHFS ‣ ίʔυ͹͔ͬόʔδϣϯ ‣ IUUQTTQFBLFSEFDLDPNMWMBIPXUPJNQMFNFOUDVTUPN MBZPVUNBOBHFS ‣ -JOFBS-BZPVU.BOBHFSͷϛχϚϜ࣮૷Ͱ-BZPVU.BOBHFSͷ࣮૷ํ๏

    Λ঺հ͍ͯ͠Δࢿྉ ิ଍ࢿྉ
  75. 5IBOLZPV