RecyclerView.ItemAnimator

5f533179da1c82722252cbcb93e7356f?s=47 Moyuru Aizawa
September 27, 2019

 RecyclerView.ItemAnimator

5f533179da1c82722252cbcb93e7356f?s=128

Moyuru Aizawa

September 27, 2019
Tweet

Transcript

  1. RecyclerView.ItemAnimator @MoyuruAizawa

  2. MoyuruAizawa Moyuru Aizawa
 Software Engineer of Azit Inc. and RABO

    Inc. Previously at CyberAgent Inc. and Eureka Inc.
  3. RecyclerViewγϦʔζ☺

  4. ‣ RecyclerView.LayoutManager ‣ RecyclerView.ItemDecoration ‣ RecyclerView.RecycledViewPool ‣ RecyclerView.ItemAnimator ‣ https://speakerdeck.com/lvla

    RecyclerViewγϦʔζ☺
  5. ‣ RecyclerView.Adapterʹมߋ͕ੜͨ࣌͡ͷΞχϝʔγϣϯΛఆٛ͢Δ ‣ ௥Ճ ‣ ࡟আ ‣ Ҡಈ ‣ มߋ

    ‣ Predictive Animations RecyclerView.ItemAnimator
  6. ‣ RecyclerView.ItemAnimatorΛܧঝͨ͠ந৅Ϋϥε ‣ ࢖͍·Θͤͦ͏ͳॲཧΛ༧Ί࣮૷ͯ͘͠ΕͯΔ ‣ 2ݸؔ਺Λ࣮૷͢Ε͹ͱΓ͋͑ͣ͸Ξχϝʔγϣϯͤ͞ΕΔ SimpleItemAnimator

  7. ‣ SimpleItemAnimator#animateXxx [Add | Remove | Move | Change] ‣

    SimpleItemAnimator#runPendingAnimations ‣ SimpleItemAnimator#isRunning ‣ SimpleItemAnimator#endAnimation ‣ SimpleItemAnimator#endAnimations SimpleItemAnimator
  8. ‣ SimpleItemAnimator#animateXxx [Add | Remove | Move | Change] ‣

    SimpleItemAnimator#runPendingAnimations ‣ SimpleItemAnimator#isRunning ‣ SimpleItemAnimator#endAnimation ‣ SimpleItemAnimator#endAnimations SimpleItemAnimator
  9. ‣ ࣮ߦ͍ͨ͠ΞχϝʔγϣϯΛఆٛ͢Δؔ਺ ‣ ͜ͷؔ਺಺Ͱ͸ΞχϝʔγϣϯΛ࣮ߦ͠ͳ͍ ‣ animateAddͰfade in͍ͤͨ͞৔߹ ‣ ViewͷalphaΛ0ʹ͓ͯ͘͠ ‣

    alphaΛ0->1ʹ͢ΔAnimationΛ૊Έཱ͓ͯͯ͘ SimpleItemAnimator#animateXxx
  10. ‣ SimpleItemAnimator#animateXxxͰఆٛͨ͠ΞχϝʔγϣϯΛ࣮ߦ͢ Δؔ਺ SimpleItemAnimator#runPendingAnimations

  11. ‣ Ξχϝʔγϣϯத͔Ͳ͏͔ฦ͢ SimpleItemAnimator#isRunning

  12. ‣ ΞχϝʔγϣϯΛଈ࠲ʹऴྃ͢΂͖ͱ͖ʹݺ͹ΕΔ ‣ εΫϩʔϧͳͲͷΠϕϯτ࣌ʹݺ͹ΕΔ ‣ Fade inΞχϝʔγϣϯͷ৔߹ ‣ ΞχϝʔγϣϯΛΩϟϯηϧ͢Δ ‣

    alphaΛ1ʹมߋ͢Δ SimpleItemAnimator#endAnimation / endAnimations
  13. class Animator : SimpleItemAnimator() { private val pendingAnimators = LinkedList<ViewPropertyAnimatorCompat>()

    private val runningAnimators = LinkedList<ViewPropertyAnimatorCompat>() … override fun animateAdd(holder: RecyclerView.ViewHolder): Boolean { holder.itemView.alpha = 0f ViewCompat.animate(holder.itemView) .alpha(1f) .setDuration(addDuration) .setInterpolator(DecelerateInterpolator()) .let(pendingAnimators::add) return true } } SimpleItemAnimator#animateAdd
  14. class Animator : SimpleItemAnimator() { private val pendingAnimators = LinkedList<ViewPropertyAnimatorCompat>()

    private val runningAnimators = LinkedList<ViewPropertyAnimatorCompat>() … override fun animateAdd(holder: RecyclerView.ViewHolder): Boolean { holder.itemView.alpha = 0f ViewCompat.animate(holder.itemView) .alpha(1f) .setDuration(addDuration) .setInterpolator(DecelerateInterpolator()) .let(pendingAnimators::add) return true } } SimpleItemAnimator#animateAdd
  15. class Animator : SimpleItemAnimator() { private val pendingAnimators = LinkedList<ViewPropertyAnimatorCompat>()

    private val runningAnimators = LinkedList<ViewPropertyAnimatorCompat>() … override fun animateAdd(holder: RecyclerView.ViewHolder): Boolean { holder.itemView.alpha = 0f ViewCompat.animate(holder.itemView) .alpha(1f) .setDuration(addDuration) .setInterpolator(DecelerateInterpolator()) .let(pendingAnimators::add) return true } } SimpleItemAnimator#animateAdd
  16. class Animator : SimpleItemAnimator() { private val pendingAnimators = LinkedList<ViewPropertyAnimatorCompat>()

    private val runningAnimators = LinkedList<ViewPropertyAnimatorCompat>() … override fun animateAdd(holder: RecyclerView.ViewHolder): Boolean { holder.itemView.alpha = 0f ViewCompat.animate(holder.itemView) .alpha(1f) .setDuration(addDuration) .setInterpolator(DecelerateInterpolator()) .let(pendingAnimators::add) return true } } SimpleItemAnimator#animateAdd
  17. class Animator : SimpleItemAnimator() { … override fun runPendingAnimations() {

    pendingAnimators.forEach { animation -> animation.setListener(object : ViewPropertyAnimatorListener { override fun onAnimationStart(view: View?) { runningAnimators.add(animation) } override fun onAnimationEnd(view: View?) { runningAnimators.remove(animation) } override fun onAnimationCancel(view: View?) { runningAnimators.remove(animation) } }).start() pendingAnimators.clear() } } } SimpleItemAnimator#pendingAnimations
  18. class Animator : SimpleItemAnimator() { … override fun runPendingAnimations() {

    pendingAnimators.forEach { animation -> animation.setListener(object : ViewPropertyAnimatorListener { override fun onAnimationStart(view: View?) { runningAnimators.add(animation) } override fun onAnimationEnd(view: View?) { runningAnimators.remove(animation) } override fun onAnimationCancel(view: View?) { runningAnimators.remove(animation) } }).start() pendingAnimators.clear() } } } SimpleItemAnimator#pendingAnimations
  19. class Animator : SimpleItemAnimator() { … override fun runPendingAnimations() {

    pendingAnimators.forEach { animation -> animation.setListener(object : ViewPropertyAnimatorListener { override fun onAnimationStart(view: View?) { runningAnimators.add(animation) } override fun onAnimationEnd(view: View?) { runningAnimators.remove(animation) } override fun onAnimationCancel(view: View?) { runningAnimators.remove(animation) } }).start() pendingAnimators.clear() } } } SimpleItemAnimator#pendingAnimations
  20. class Animator : SimpleItemAnimator() { … override fun runPendingAnimations() {

    pendingAnimators.forEach { animation -> animation.setListener(object : ViewPropertyAnimatorListener { override fun onAnimationStart(view: View?) { runningAnimators.add(animation) } override fun onAnimationEnd(view: View?) { runningAnimators.remove(animation) } override fun onAnimationCancel(view: View?) { runningAnimators.remove(animation) } }).start() pendingAnimators.clear() } } } SimpleItemAnimator#pendingAnimations
  21. class Animator : SimpleItemAnimator() { … override fun runPendingAnimations() {

    pendingAnimators.forEach { animation -> animation.setListener(object : ViewPropertyAnimatorListener { override fun onAnimationStart(view: View?) { runningAnimators.add(animation) } override fun onAnimationEnd(view: View?) { runningAnimators.remove(animation) } override fun onAnimationCancel(view: View?) { runningAnimators.remove(animation) } }).start() pendingAnimators.clear() } } } SimpleItemAnimator#pendingAnimations
  22. class Animator : SimpleItemAnimator() { private val runningAnimators = LinkedList<ViewPropertyAnimatorCompat>()

    override fun isRunning() = runningAnimators.isNotEmpty() override fun endAnimation(item: RecyclerView.ViewHolder) { item.itemView.animation?.cancel() item.itemView.alpha = 1f } … } SimpleItemAnimator#isRunning, endAnimation
  23. Predictive Animations Predictive Animations Predictive Animations

  24. ‣ ૿ݮ͢ΔΞΠςϜͷΞχϝʔγϣϯʹ߹ΘͤͯલޙͷΞΠςϜͷҐஔ Λௐ੔͢Δ ‣ LayoutManager͕Predictive AnimationsʹରԠ͍ͯ͠Δඞཁ͕͋Δ
 (LinearLayoutManager, GridLayoutManager…) ‣ SimpleItemAnimator͸Predictive

    Animationsͷ࣮૷΋؆୯ ‣ SimpleItemAnimator#animateMoveΛ࣮૷͢Δ͚ͩ Predictive Animations
  25. class Animator : SimpleItemAnimator() { … override fun animateMove( holder:

    RecyclerView.ViewHolder, fromX: Int, fromY: Int, toX: Int, toY: Int ): Boolean { holder.itemView.y = fromY.toFloat() ViewCompat.animate(holder.itemView) .y(toY.toFloat()) .setDuration(moveDuration) .setInterpolator(DecelerateInterpolator()) .let(pendingAnimators::add) return true } } SimpleItemAnimator#animateMove
  26. class Animator : SimpleItemAnimator() { … override fun animateMove( holder:

    RecyclerView.ViewHolder, fromX: Int, fromY: Int, toX: Int, toY: Int ): Boolean { holder.itemView.y = fromY.toFloat() ViewCompat.animate(holder.itemView) .y(toY.toFloat()) .setDuration(moveDuration) .setInterpolator(DecelerateInterpolator()) .let(pendingAnimators::add) return true } } SimpleItemAnimator#animateMove
  27. class Animator : SimpleItemAnimator() { … override fun animateMove( holder:

    RecyclerView.ViewHolder, fromX: Int, fromY: Int, toX: Int, toY: Int ): Boolean { holder.itemView.y = fromY.toFloat() ViewCompat.animate(holder.itemView) .y(toY.toFloat()) .setDuration(moveDuration) .setInterpolator(DecelerateInterpolator()) .let(pendingAnimators::add) return true } } SimpleItemAnimator#animateMove
  28. Thank You