Slide 1

Slide 1 text

animation 11% animation +1 % 1

Slide 2

Slide 2 text

안성용 Sungyong An 네이버웹툰

Slide 3

Slide 3 text

animation 11% • "a method in which pictures are manipulated to appear as moving images." Animation Link: https://en.wikipedia.org/wiki/Animation

Slide 4

Slide 4 text

Animation

Slide 5

Slide 5 text

animation 11% Animation Category ੿ܻೞӝ ݾ಴

Slide 6

Slide 6 text

animation 11% • Drawable Animation • StateListAnimator • ViewPropertyAnimator • DynamicAnimation • View Animation • Shared Elements • Lottie (3rd party) • Interpolator • Animator • LayoutTransition • CircularReveal • Transition • MotionLayout ❌ animation

Slide 7

Slide 7 text

animation 11% Lottie (3rd party) Drawable Animation StateListAnimator ViewPropertyAnimator DynamicAnimation View Animation Shared Elements Interpolator Animator Transition CircularReveal MotionLayout LayoutTransition animation View inner Multiple views Single view Between screens

Slide 8

Slide 8 text

animation 11% Animate view inner View ղࠗ গפݫ੉࣌

Slide 9

Slide 9 text

Animation Drawable

Slide 10

Slide 10 text

animation 11% • res/drawable/ic_battery_anim.xml AnimationDrawable ...

Slide 11

Slide 11 text

animation 11% • res/drawable/ic_battery_anim.xml AnimationDrawable ...

Slide 12

Slide 12 text

animation 11% • res/drawable/ic_battery_anim.xml AnimationDrawable ...

Slide 13

Slide 13 text

animation 11% AnimationDrawable // AnimationDrawable.java private void setFrame( int frame, boolean unschedule, boolean animate) { ... selectDrawable(frame); ... scheduleSelf(this, SystemClock.uptimeMillis() + mAnimationState.mDurations[frame]); }

Slide 14

Slide 14 text

animation 11% AnimationDrawable // AnimationDrawable.java private void setFrame( int frame, boolean unschedule, boolean animate) { ... selectDrawable(frame); ... scheduleSelf(this, SystemClock.uptimeMillis() + mAnimationState.mDurations[frame]); }

Slide 15

Slide 15 text

animation 11% AnimationDrawable // AnimationDrawable.java private void setFrame( int frame, boolean unschedule, boolean animate) { ... selectDrawable(frame); ... scheduleSelf(this, SystemClock.uptimeMillis() + mAnimationState.mDurations[frame]); }

Slide 16

Slide 16 text

Animated StateList Drawable API 21

Slide 17

Slide 17 text

animation 11% AnimatedStateListDrawable

Slide 18

Slide 18 text

animation 11% AnimatedStateListDrawable 32 32 32 32 32 32 32 32

Slide 19

Slide 19 text

animation 11% AnimatedStateListDrawable

Slide 20

Slide 20 text

animation 11% AnimatedStateListDrawable

Slide 21

Slide 21 text

animation 11% android:id="@+id/selected" android:drawable="@drawable/ic_battery_100" android:state_checked="true" /> AnimatedStateListDrawable

Slide 22

Slide 22 text

animation 11% ... AnimatedStateListDrawable

Slide 23

Slide 23 text

animation 11% AnimatedStateListDrawable

Slide 24

Slide 24 text

+ Animated Vector Drawable API 21

Slide 25

Slide 25 text

animation 11% + AnimatedVectorDrawable

Slide 26

Slide 26 text

animation 11% + AnimatedVectorDrawable 0 400 420 570 720 750 950

Slide 27

Slide 27 text

animation 11% + AnimatedVectorDrawable

Slide 28

Slide 28 text

animation 11% + AnimatedVectorDrawable

Slide 29

Slide 29 text

animation 11% + AnimatedVectorDrawable

Slide 30

Slide 30 text

animation 11% + AnimatedVectorDrawable

Slide 31

Slide 31 text

animation 11% + AnimatedVectorDrawable

Slide 32

Slide 32 text

animation 11% + AnimatedVectorDrawable

Slide 33

Slide 33 text

animation 11%

Slide 34

Slide 34 text

animation 11%

Slide 35

Slide 35 text

animation 11% android:pathData="M 9.5 15 C 10.881 15 12 ..." android:fillColor="#ffffff" android:fillAlpha="0.7"/>

Slide 36

Slide 36 text

animation 11%

Slide 37

Slide 37 text

animation 11%

Slide 38

Slide 38 text

animation 11% android:interpolator="@android:interpolator/linear_out_slow_in"/> + AnimatedVectorDrawable

Slide 39

Slide 39 text

animation 11% + AnimatedVectorDrawable

Slide 40

Slide 40 text

Seekable A nimated V ector D rawable

Slide 41

Slide 41 text

animation 11% val savd = SeekableAnimatedVectorDrawable.create(context, R.drawable.avd) imageView.setImageDrawable(savd) savd?.start() // seekable savd?.currentPlayTime = 100L Seekable A V D

Slide 42

Slide 42 text

animation 11% Progress Bar Rotate Drawable

Slide 43

Slide 43 text

animation 11% ProgressBar + RotateDrawable

Slide 44

Slide 44 text

animation 11% ProgressBar + RotateDrawable

Slide 45

Slide 45 text

animation 11% ProgressBar + RotateDrawable

Slide 46

Slide 46 text

animation 11% ProgressBar + RotateDrawable

Slide 47

Slide 47 text

animation 11% ProgressBar + RotateDrawable

Slide 48

Slide 48 text

animation 11% Progress Bar Clip Drawable

Slide 49

Slide 49 text

animation 11% ProgressBar + ClipDrawable

Slide 50

Slide 50 text

animation 11% ProgressBar + ClipDrawable

Slide 51

Slide 51 text

animation 11% ProgressBar + ClipDrawable

Slide 52

Slide 52 text

animation 11% ProgressBar + ClipDrawable

Slide 53

Slide 53 text

Ripple Drawable API 21

Slide 54

Slide 54 text

animation 11% Ripple Drawable

Slide 55

Slide 55 text

animation 11% RippleDrawable

Slide 56

Slide 56 text

animation 11% RippleDrawable

Slide 57

Slide 57 text

animation 11% RippleDrawable

Slide 58

Slide 58 text

animation 11% RippleDrawable

Slide 59

Slide 59 text

animation 11% RippleDrawable

Slide 60

Slide 60 text

StateList Animator API 21

Slide 61

Slide 61 text

animation 11% StateList Animator

Slide 62

Slide 62 text

animation 11% StateList Animator

Slide 63

Slide 63 text

animation 11% StateList Animator

Slide 64

Slide 64 text

animation 11% StateList Animator

Slide 65

Slide 65 text

animation 11% StateList Animator

Slide 66

Slide 66 text

animation 11% Animate single view ױੌ View গפݫ੉࣌

Slide 67

Slide 67 text

View Property Animator API 12

Slide 68

Slide 68 text

animation 11% View Property Animator view.animate() // ViewPropertyAnimator

Slide 69

Slide 69 text

animation 11% view.animate() .translationX(100f) View Property Animator

Slide 70

Slide 70 text

animation 11% view.animate() .translationX(100f) .setStartDelay(300L) // ms .setDuration(1000L) // ms .setInterpolator(Interpolators.ACCELERATE_DECELERATE) View Property Animator

Slide 71

Slide 71 text

animation 11% view.animate() .translationX(100f) .translationY(50f) .rotation(90f) .scaleX(1.5f) .scaleY(0.5f) .alpha(1f) View Property Animator

Slide 72

Slide 72 text

animation 11% view.animate().cancel() view.translationX = 0f view.animate() .translationX(100f) View Property Animator

Slide 73

Slide 73 text

animation 11% view.animate().cancel() view.translationX = currentTranslationX view.animate() .translationX(100f) View Property Animator

Slide 74

Slide 74 text

animation 11% view.animate().cancel() view.translationX = view.translationX view.animate() .translationX(100f) View Property Animator

Slide 75

Slide 75 text

animation 11% view.animate().cancel() // view.translationX = view.translationX view.animate() .translationX(100f) View Property Animator

Slide 76

Slide 76 text

animation 11% view.animate() .translationX(100f) .withLayer() ❓ API 16 View Property Animator

Slide 77

Slide 77 text

animation 11% Render into off-screen buffers. View Layer (Hardware vs Software) Link: Android Graphics Performance (Google I/O '13) API 11

Slide 78

Slide 78 text

animation 11% Hardware Layer view.setLayerType(View.LAYER_TYPE_HARDWARE, null) // do animate! Link: https://developer.android.com/guide/topics/graphics/hardware-accel#layers

Slide 79

Slide 79 text

animation 11% Hardware Layer view.setLayerType(View.LAYER_TYPE_HARDWARE, null) // do animate! view.setLayerType(View.LAYER_TYPE_NONE, null) Link: https://developer.android.com/guide/topics/graphics/hardware-accel#layers

Slide 80

Slide 80 text

animation 11% Hardware Layer view.animate() .withLayer() Link: https://developer.android.com/guide/topics/graphics/hardware-accel#layers API 16

Slide 81

Slide 81 text

animation 11% • Viewী Alphaܳ ࢎਊೞח ҃਋, Viewܳ ࢚ࣘ೧ࢲ falseܳ ߈ജೞח Ѫ੉ ࢿמী ਬܻೞ׮. • ױ, View ղࠗ ਃٜࣗ੉ Ҁ஖૑ ঋইঠ ৢ߄ܰѱ Ӓ۰૓׮. An optimization when alpha is set on a view. View#hasOverlappingRendering() Link: Hidden Cost of Transparency (100 Days of Google Dev) API 16

Slide 82

Slide 82 text

animation 11% View#hasOverlappingRendering()

Slide 83

Slide 83 text

animation 11% View#hasOverlappingRendering()

Slide 84

Slide 84 text

animation 11% View#hasOverlappingRendering()

Slide 85

Slide 85 text

animation 11% View#hasOverlappingRendering()

Slide 86

Slide 86 text

animation 11% View#hasOverlappingRendering()

Slide 87

Slide 87 text

animation 11% View#hasOverlappingRendering() < AlphaOptimizedConstraintLayout android:alpha="0.5">

Slide 88

Slide 88 text

animation 11% View#hasOverlappingRendering() class AlphaOptimizedConstraintLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : ConstraintLayout(context, attrs, defStyleAttr) { override fun hasOverlappingRendering(): Boolean { return false } } Link: AlphaOptimizedFrameLayout.java

Slide 89

Slide 89 text

Dynamic Animation

Slide 90

Slide 90 text

animation 11% • app/build.gradle DynamicAnimation implementation 'androidx.dynamicanimation:dynamicanimation:1.1.0-alpha02' implementation 'androidx.dynamicanimation:dynamicanimation-ktx:1.0.0-alpha02' API 11

Slide 91

Slide 91 text

animation 11% SpringAnimation val spring = SpringAnimation( view, DynamicAnimation.TRANSLATION_X, 300f) .withSpringForceProperties { dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY stiffness = SpringForce.STIFFNESS_LOW } spring.start()

Slide 92

Slide 92 text

animation 11% SpringAnimation val spring = SpringAnimation( view, DynamicAnimation.TRANSLATION_X, 300f) .withSpringForceProperties { dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY stiffness = SpringForce.STIFFNESS_LOW } spring.start()

Slide 93

Slide 93 text

animation 11% SpringAnimation val spring = SpringAnimation( view, DynamicAnimation.TRANSLATION_X) .withSpringForceProperties { dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY stiffness = SpringForce.STIFFNESS_LOW } spring.animateToFinalPosition(300f)

Slide 94

Slide 94 text

animation 11% SpringAnimation val spring = SpringAnimation( view, DynamicAnimation.TRANSLATION_X) .withSpringForceProperties { dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY stiffness = SpringForce.STIFFNESS_LOW } spring.animateToFinalPosition(300f) spring.animateToFinalPosition(0f)

Slide 95

Slide 95 text

animation 11% SpringAnimation val spring = SpringAnimation( view, DynamicAnimation.TRANSLATION_X) .withSpringForceProperties { dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY stiffness = SpringForce.STIFFNESS_LOW } spring.animateToFinalPosition(300f) spring.animateToFinalPosition(0f) spring.animateToFinalPosition(500f)

Slide 96

Slide 96 text

Link: Motional Intelligence: Build Smarter Animations (Google I/O'19)

Slide 97

Slide 97 text

Link: Motional Intelligence: Build Smarter Animations (Google I/O'19)

Slide 98

Slide 98 text

Link: Motional Intelligence: Build Smarter Animations (Google I/O'19)

Slide 99

Slide 99 text

Link: Motional Intelligence: Build Smarter Animations (Google I/O'19)

Slide 100

Slide 100 text

Link: Motional Intelligence: Build Smarter Animations (Google I/O'19)

Slide 101

Slide 101 text

animation 11% Interpolator

Slide 102

Slide 102 text

Interpolator

Slide 103

Slide 103 text

animation 11% • 0f, 1f ࢎ੉੄ чਸ ੸੺ೞѱ ࠁрػ чਵ۽ ߈ജೠ׮. • ઺р੄ ч਷ 0f ~ 1f ߧਤܳ ߩযզ ࣻ ੓૑݅, द੘җ ՘਷ 0f, 1fܳ ࠁ੢ೠ׮. • ױࣽ൤ Inputী Outputਸ ߈ജೞח Ѫ੉޲۽, Singletonਵ۽ ࢎਊೡ ࣻ ੓׮. Animation੉ ߸ചೞח ੿ب Interpolator

Slide 104

Slide 104 text

animation 11% Interpolator // package android.animation; public interface TimeInterpolator { // input : 0 and 1.0 // output: The interpolation value. float getInterpolation(float input); } // package android.view.animation; public interface Interpolator extends TimeInterpolator { }

Slide 105

Slide 105 text

animation 11% Interpolator Link: android/view/animation/AnimationUtils.java#408 • res/interpolator/{file_name}.xml -> LinearInterpolator -> AccelerateInterpolator -> DecelerateInterpolator -> AccelerateDecelerateInterpolator -> CycleInterpolator -> AnticipateInterpolator -> OvershootInterpolator -> AnticipateOvershootInterpolator -> BounceInterpolator -> PathInterpolator

Slide 106

Slide 106 text

animation 11% Interpolator AnimationUtils.loadInterpolator( context, android.R.interpolator.linear) val animation: Animation = ... animation.setInterpolator( context, android.R.interpolator.linear)

Slide 107

Slide 107 text

animation 11% PathInterpolator android.view.animation API 21

Slide 108

Slide 108 text

animation 11% PathInterpolator android.view.animation // Quad PathInterpolator(0.33f, 0f) // Cubic PathInterpolator(0.33f, 0f, 1f, 1f) // Path PathInterpolator(Path().apply { moveTo(0f,0f) lineTo(1f, 0f) lineTo(0f, 1f) }) API 21

Slide 109

Slide 109 text

animation 11% PathInterpolatorCompat androidx.core.view.animation // Quad PathInterpolatorCompat.create(0.33f, 0f) // Cubic PathInterpolatorCompat.create(0.33f, 0f, 1f, 1f) // Path PathInterpolatorCompat.create(Path().apply { moveTo(0f,0f) lineTo(1f, 0f) lineTo(0f, 1f) }) implementation 'androidx.interpolator:interpolator:1.0.0' API 14

Slide 110

Slide 110 text

animation 11% Link: https://easings.net/ Easing Interpolator

Slide 111

Slide 111 text

animation 11% Easing Interpolator Link: https://easings.net/

Slide 112

Slide 112 text

animation 11% Easing Interpolator val EASE_IN_OUT_CUBIC by cubicBezier(0.645f, 0.045f, 0.355f, 1f) private fun cubicBezier( x1: Float, y1: Float, x2: Float, y2: Float ): Lazy { return lazy { PathInterpolatorCompat.create(x1, y1, x2, y2) } }

Slide 113

Slide 113 text

animation 11% Animate multiple views ৈ۞ View গפݫ੉࣌

Slide 114

Slide 114 text

animation 11% • XML ౵ੌ۽ ࢶ঱ೡ ࣻ ੓׮. • VSYNC৬ োزೞৈ 60fps۽ ز੘ೠ׮. package android.animation Animator

Slide 115

Slide 115 text

animation 11% AnimatorInflater Link: http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/ animation/AnimatorInflater.java#666 • res/animator/{file_name}.xml -> AnimatorSet -> ValueAnimator -> ObjectAnimator -> PropertyValuesHolder[]

Slide 116

Slide 116 text

animation 11% Animator abstract class Animator class AnimatorSet extends Animator class ValueAnimator extends Animator class ObjectAnimator extends ValueAnimator class TimeAnimator extends ValueAnimator

Slide 117

Slide 117 text

animation 11% The VSYNC signal synchronizes the display pipeline. (60fps) VSYNC (Vertical Synchronization)

Slide 118

Slide 118 text

animation 11% • ValueAnimatorо Choreographerܳ ੉ਊೠ׮. VSYNCܳ ੉ਊೞৈ, ٣झ೒ۨ੉ ೐ۨ੐ ۪؊݂ झாેਸ ҙܻ Choreographer Link: https://developer.android.com/reference/android/view/Choreographer API 16

Slide 119

Slide 119 text

animation 11% Choreographer val choreographer = Choreographer.getInstance() choreographer.postFrameCallback { // draw next frame }

Slide 120

Slide 120 text

animation 11% Choreographer val choreographer = Choreographer.getInstance() choreographer.postFrameCallback { // draw next frame } // Not this view.post() // But this view.postOnAnimation { ... }

Slide 121

Slide 121 text

animation 11% Choreographer val choreographer = Choreographer.getInstance() choreographer.postFrameCallback { // draw next frame } // Not this view.invalidate() // But this view.postInvalidateOnAnimation()

Slide 122

Slide 122 text

animation 11% public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback { private void start(boolean playBackwards) { ... AnimationHandler.getInstance() .addAnimationFrameCallback(this, delay); ... } public final boolean doAnimationFrame(long frameTime) {} } public class AnimationHandler { Choreographer: Animator

Slide 123

Slide 123 text

animation 11% private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { doAnimationFrame(getProvider().getFrameTime()); Choreographer.getInstance() .postFrameCallback(mFrameCallback); } }; public void addAnimationFrameCallback(...) { Choreographer.getInstance() .postFrameCallback(mFrameCallback); } } Choreographer: Animator

Slide 124

Slide 124 text

animation 11% ... } public final boolean doAnimationFrame(long frameTime) {} } public class AnimationHandler { private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { doAnimationFrame(getProvider().getFrameTime()); Choreographer.getInstance() .postFrameCallback(mFrameCallback); } }; public void addAnimationFrameCallback(...) { Choreographer.getInstance() .postFrameCallback(mFrameCallback); Choreographer: Animator

Slide 125

Slide 125 text

animation 11% public final boolean doAnimationFrame(long frameTime) {} } public class AnimationHandler { private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { doAnimationFrame(getProvider().getFrameTime()); Choreographer.getInstance() .postFrameCallback(mFrameCallback); } }; public void addAnimationFrameCallback(...) { Choreographer.getInstance() .postFrameCallback(mFrameCallback); } } Choreographer: Animator

Slide 126

Slide 126 text

animation 11% public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback { private void start(boolean playBackwards) { ... AnimationHandler.getInstance() .addAnimationFrameCallback(this, delay); ... } public final boolean doAnimationFrame(long frameTime) {} } public class AnimationHandler { private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { doAnimationFrame(getProvider().getFrameTime()); Choreographer: Animator

Slide 127

Slide 127 text

Animator API 11

Slide 128

Slide 128 text

animation 11% Animator ValueAnimator.ofFloat(0f, 1f).apply { repeatMode = ValueAnimator.REVERSE repeatCount = ValueAnimator.INFINITE duration = 1_000L interpolator = Interpolators.ACCELERATE_DECELERATE }

Slide 129

Slide 129 text

animation 11% Animator

Slide 130

Slide 130 text

animation 11% Animator

Slide 131

Slide 131 text

animation 11% Animator floatType intType pathType colorType

Slide 132

Slide 132 text

animation 11% Animator ValueAnimator.ofFloat() ValueAnimator.ofInt() ValueAnimator.ofPropertyValuesHolder() ValueAnimator.ofArgb()

Slide 133

Slide 133 text

animation 11% Animator FloatEvaluator() IntEvaluator() PathDataEvaluator() ArgbEvaluator()

Slide 134

Slide 134 text

animation 11% Animator

Slide 135

Slide 135 text

animation 11% Animator

Slide 136

Slide 136 text

animation 11% Animator ValueAnimator.ofFloat(0f, 1f).apply { repeatMode = ValueAnimator.REVERSE repeatCount = ValueAnimator.INFINITE duration = 1_000L interpolator = Interpolators.ACCELERATE_DECELERATE }

Slide 137

Slide 137 text

animation 11% val animator = ValueAnimator.ofFloat(0f, 1f).apply { repeatMode = ValueAnimator.REVERSE repeatCount = ValueAnimator.INFINITE duration = 1_000L interpolator = Interpolators.ACCELERATE_DECELERATE } Animator

Slide 138

Slide 138 text

animation 11% val animator = ValueAnimator.ofFloat(0f, 1f).apply { repeatMode = ValueAnimator.REVERSE repeatCount = ValueAnimator.INFINITE duration = 1_000L interpolator = Interpolators.ACCELERATE_DECELERATE } animator.addUpdateListener { updateUi(it.animatedFraction) // or updateUi(it.animatedValue as Float) } animator.removeAllUpdateListeners() animator.start() animator.cancel() Animator

Slide 139

Slide 139 text

animation 11% updateUi(it.animatedFraction) Animator

Slide 140

Slide 140 text

animation 11% Animator private fun updateUi(fraction: Float) { iconView.run { rotation = lerp(0f, 360f, fraction) alpha = lerp(1f, .5f, fraction) scaleX = lerp(1f, 2f, fraction) scaleY = lerp(1f, .5f, fraction) translationX = lerp(0f, maxTranslationX, fraction) translationY = lerp(0f, maxTranslationY, fraction) } bugView.translationX = lerp(0f, maxTranslationX, fraction) }

Slide 141

Slide 141 text

animation 11% Lerp fun lerp(from: Float, to: Float, progress: Float): Float { return from + (to - from) * progress }

Slide 142

Slide 142 text

Layout Transition API 11

Slide 143

Slide 143 text

animation 11% LayoutTransition container.addView(...) container.removeView(...) container.childAt(...).setVisibility(...)

Slide 144

Slide 144 text

animation 11% LayoutTransition // ViewGroup.java case R.styleable.ViewGroup_animateLayoutChanges: boolean animateLayoutChanges = a.getBoolean(attr, false); if (animateLayoutChanges) { setLayoutTransition(new LayoutTransition()); } break;

Slide 145

Slide 145 text

animation 11% PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1); PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1); PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 1); PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1); PropertyValuesHolder pvhScrollX = PropertyValuesHolder.ofInt("scrollX", 0, 1); PropertyValuesHolder pvhScrollY = PropertyValuesHolder.ofInt("scrollY", 0, 1); defaultChange = ObjectAnimator.ofPropertyValuesHolder((Object)null, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScrollX, pvhScrollY); defaultFadeIn = ObjectAnimator.ofFloat(null, "alpha", 0f, 1f); defaultFadeOut = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f); LayoutTransition

Slide 146

Slide 146 text

animation 11% container.layoutTransition.apply { setInterpolator(LayoutTransition.APPEARING, Interpolators.ACCELERATE_DECELERATE) setDuration(LayoutTransition.APPEARING, 300) } // LayoutTransition.APPEARING // LayoutTransition.DISAPPEARING // LayoutTransition.CHANGE_APPEARING // LayoutTransition.CHANGE_DISAPPEARING // LayoutTransition.CHANGING LayoutTransition

Slide 147

Slide 147 text

Transition API 19

Slide 148

Slide 148 text

animation 11% Transition TransitionManager.beginDelayedTransition(container) outerBackground.visibility = View.GONE innerBackground.visibility = View.GONE

Slide 149

Slide 149 text

animation 11% Transition TransitionManager.beginDelayedTransition(container) outerBackground.visibility = View.VISIBLE innerBackground.visibility = View.VISIBLE

Slide 150

Slide 150 text

animation 11% Transition TransitionManager.beginDelayedTransition(container, AutoTransition()) outerBackground.visibility = View.VISIBLE innerBackground.visibility = View.VISIBLE

Slide 151

Slide 151 text

animation 11% Transition val transition = TransitionInflater.from(it.context) .inflateTransition(R.transition.auto_transition) TransitionManager.beginDelayedTransition(container, transition) outerBackground.visibility = View.VISIBLE innerBackground.visibility = View.VISIBLE

Slide 152

Slide 152 text

animation 11% Transition =

Slide 153

Slide 153 text

animation 11% TransitionInflater Link: http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/ transition/TransitionInflater.java#148 • res/transition/{file_name}.xml ... -> AutoTransition -> Fade -> ChangeBounds -> Slide -> Explode -> ChangeImageTransform -> ChangeTransform -> ChangeClipBounds -> TransitionSet ...

Slide 154

Slide 154 text

animation 11% • TransitionValuesח View ё୓৬ View IDী ӝ߈ೞৈ ஭୊ػ׮. Transition public abstract class Transition { public abstract void captureStartValues( TransitionValues transitionValues); public abstract void captureEndValues( TransitionValues transitionValues); protected void animate(Animator animator) { ... } }

Slide 155

Slide 155 text

Motion Layout

Slide 156

Slide 156 text

animation 11% Motion Layout

Slide 157

Slide 157 text

animation 11% Motion Layout

Slide 158

Slide 158 text

animation 11% Motion Layout

Slide 159

Slide 159 text

animation 11% Motion Layout

Slide 160

Slide 160 text

animation 11% Motion Layout // Start transition motionLayout.transitionToStart() motionLayout.transitionToEnd() // Reset transition motionLayout.setTransition(R.id.start, R.id.end) // Seekable transition motionLayout.progress = 0f // ~ 1f

Slide 161

Slide 161 text

Circular Reveal API 21

Slide 162

Slide 162 text

animation 11% Circular Reveal

Slide 163

Slide 163 text

animation 11% // Show revealView.showContents() private fun View.showContents() { visibility = View.VISIBLE createCircularRevealOf(fab, 0f, radius) { duration = 300 interpolator = Interpolators.DECELERATE }.start() } // Hide revealView.hideContents() private fun View.hideContents() { Circular Reveal

Slide 164

Slide 164 text

animation 11% createCircularRevealOf(fab, 0f, radius) { duration = 300 interpolator = Interpolators.DECELERATE }.start() } // Hide revealView.hideContents() private fun View.hideContents() { createCircularRevealOf(fab, radius, 0f) { duration = 300 interpolator = Interpolators.ACCELERATE doOnEnd { visibility = View.GONE } }.start() } private inline fun View.createCircularRevealOf( target: View, Circular Reveal

Slide 165

Slide 165 text

animation 11% doOnEnd { visibility = View.GONE } }.start() } private inline fun View.createCircularRevealOf( target: View, startRadius: Float, endRadius: Float, block: Animator.() -> Unit ): Animator { return ViewAnimationUtils.createCircularReveal( this, target.centerX(), target.centerY(), startRadius, endRadius ).apply(block) } Circular Reveal

Slide 166

Slide 166 text

animation 11% Circular Reveal : MDC API 14

Slide 167

Slide 167 text

animation 11% interface CircularRevealWidget class CircularRevealLinearLayout extends LinearLayout class CircularRevealRelativeLayout extends RelativeLayout class CircularRevealGridLayout extends GridLayout class CircularRevealFrameLayout extends FrameLayout class CircularRevealCoordinatorLayout extends CoordinatorLayout class CircularRevealCardView extends MaterialCardView Circular Reveal : MDC

Slide 168

Slide 168 text

animation 11% Animate between screens ചݶ р গפݫ੉࣌

Slide 169

Slide 169 text

View Animation API 1

Slide 170

Slide 170 text

animation 11% • ViewPropertyAnimator৬ ਬࢎೞ׮. • Windowр Animationী ࢎਊೡ ࣻ ੓׮. • Activity <—> Activity • Fragment <—> Fragment package android.view.animation View Animation

Slide 171

Slide 171 text

animation 11% View Animation

Slide 172

Slide 172 text

animation 11% View Animation

Slide 173

Slide 173 text

animation 11% View Animation

Slide 174

Slide 174 text

animation 11% View Animation

Slide 175

Slide 175 text

animation 11% View Animation

Slide 176

Slide 176 text

animation 11% View Animation

Slide 177

Slide 177 text

animation 11% View Animation

Slide 178

Slide 178 text

animation 11% Window Animation activity.overridePendingTransition( R.anim.slide_in_right, // enterAnim R.anim.slide_out_left // exitAnim ) fragmentManager.beginTransaction() .setCustomAnimations( R.anim.slide_in_right, // enterAnim R.anim.slide_out_left, // exitAnim ) .replace(...) .commit()

Slide 179

Slide 179 text

Shared Elements API 21

Slide 180

Slide 180 text

animation 11% Shared Elements // Between activities val activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation( activity, Pair.create(view, view.transitionName) ) ActivityCompat.startActivity(context, intent, activityOptions.toBundle()) // Between fragments fragmentManager.beginTransaction() .addSharedElement(view, view.transitionName) .replace(...) .setReorderingAllowed(true) .commit()

Slide 181

Slide 181 text

animation 11% Shared Elements // Between activities val activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation( activity, Pair.create(view, view.transitionName) ) ActivityCompat.startActivity(context, intent, activityOptions.toBundle()) // Between fragments fragmentManager.beginTransaction() .addSharedElement(view, view.transitionName) .replace(...) .setReorderingAllowed(true) .commit()

Slide 182

Slide 182 text

animation 11% Shared Elements // In Kotlin view.transitionName = context.getString(R.string.transition_name)

Slide 183

Slide 183 text

animation 11% Shared Elements

Slide 184

Slide 184 text

animation 11% Shared Elements

Slide 185

Slide 185 text

animation 11% Shared Elements class MasterFragment : Fragment() class DetailFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) sharedElementEnterTransition = ...(R.transition.move_shared_element) sharedElementReturnTransition = ...(R.transition.move_shared_element) } }

Slide 186

Slide 186 text

animation 11% • View ղࠗ গפݫ੉࣌ • Drawable Animation • StateListAnimator • ױੌ View গפݫ੉࣌ • ViewPropertyAnimator • DynamicAnimation Summary • ৈ۞ View গפݫ੉࣌ • Animator (+ lerp) • Transition • MotionLayout • ചݶ р গפݫ੉࣌ • View Animation • SharedElements

Slide 187

Slide 187 text

animation 11% Codelab ௏٘ە ৘ઁ: https://github.com/fornewid/android-animation-11p-more

Slide 188

Slide 188 text

animation 11% Animation UseCase ҳഅ೧ࠁӝ ݾ಴

Slide 189

Slide 189 text

Before

Slide 190

Slide 190 text

After

Slide 191

Slide 191 text

animation 11% • AnimatedVectorDrawable • ইې ܻࣗझܳ ࢎਊೞৈ Splash Animationਸ ҳഅ೧ࠁࣁਃ. • ic_splash.svg • ic_splash_blink.svg • Tip: Shape Shifter ࢎਊೡ Ѫ Splash

Slide 192

Slide 192 text

animation 11% PathData р morphܳ ਊ੉ೞѱ ೞח ӝמ੉ ઁҕػ׮. Shape Shifter Link: https://shapeshifter.design/

Slide 193

Slide 193 text

animation 11% Splash val avd = AnimatedVectorDrawableCompat .create(this, R.drawable.avd_splash) splashIcon.setImageDrawable(avd) avd?.start()

Slide 194

Slide 194 text

animation 11% • ViewPropertyAnimator • ಕ੉૑о ߸҃ؼ ٸ, ࢸݺޙ Animationਸ ҳഅ೧ࠁࣁਃ. OnBoarding

Slide 195

Slide 195 text

animation 11% OnBoarding override fun onPageSelected(...) { pagerDescription.run { text = ... animateSlideUp() } } private fun View.animateSlideUp() { animate().cancel() alpha = 0f translationY = 40f animate() .alpha(1f) .translationY(0f) .setDuration(800) .setInterpolator(Interpolators.EASE_OUT_QUINT) .withLayer() .withEndAction(null) }

Slide 196

Slide 196 text

animation 11% • AnimatedVectorDrawable • చਸ ࢶఖೡ ٸ, Animationਸ ҳഅ೧ࠁࣁਃ. • ic_home.xml • ic_settings.xml Main

Slide 197

Slide 197 text

animation 11% Main

Slide 198

Slide 198 text

animation 11% Main

Slide 199

Slide 199 text

animation 11% • MotionLayout • SeekableAnimatedVectorDrawable • ക ചݶਸ झ௼܀ ೡ ٸ, ੹ജ Animationਸ ҳഅ೧ࠁࣁਃ. • ic_home_top.svg • ic_home_search.svg Home

Slide 200

Slide 200 text

animation 11% Home

Slide 201

Slide 201 text

animation 11% Home

Slide 202

Slide 202 text

animation 11% Home var savd = SeekableAnimatedVectorDrawable .create(view.context, R.drawable.avd_search) header.icon.setImageDrawable(it) AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset -> val progress = -verticalOffset / appBarLayout.totalScrollRange.toFloat() binding.header.root.progress = progress savd?.currentPlayTime = (100 * progress).toLong() }

Slide 203

Slide 203 text

animation 11% • StateListAnimator • Animator • ߡౡ੉ ׂ۰૑ח ബҗ৬ ೞ౟ Animationਸ ҳഅ೧ࠁࣁਃ. Detail

Slide 204

Slide 204 text

animation 11% Detail

Slide 205

Slide 205 text

animation 11% Detail private class Heart( var targetX: Float = 0f, var targetY: Float = 0f, var x: Float = 0f, var y: Float = 0f, var alpha: Float = 0f ) hearts.forEach { heart -> heart.targetX = lerp(drawableSize, width - drawableSize, random.nextFloat()) heart.targetY = lerp(drawableSize, height / 2, random.nextFloat()) } animator.start() fun lerp(from: Float, to: Float, progress: Float): Float { return (1 - progress) * from + to * progress }

Slide 206

Slide 206 text

animation 11% Detail val animator = ValueAnimator.ofFloat(0f, 1f).apply { duration = 1000 interpolator = LinearInterpolator() addUpdateListener { ... } } override fun onDraw(canvas: Canvas) { hearts.forEach { heart -> canvas.withTranslation(heart.x, heart.y) { drawable.alpha = (255 * heart.alpha).toInt() drawable.draw(canvas) } } }

Slide 207

Slide 207 text

animation 11% Detail val moveInterpolator = FastOutSlowInInterpolator() val alphaInterpolator = AccelerateInterpolator() addUpdateListener { val moveProgress = moveInterpolator.getInterpolation(it.animatedFraction) val alphaProgress = alphaInterpolator.getInterpolation(it.animatedFraction) val startX = width / 2f val startY = (height - drawableSize).toFloat() hearts.forEach { heart -> heart.x = lerp(startX, heart.targetX, moveProgress) heart.y = lerp(startY, heart.targetY, moveProgress) heart.alpha = lerp(1f, 0f, alphaProgress) } invalidate() }

Slide 208

Slide 208 text

animation 11% • DynamicAnimation • ಁօ੉ ಟ୛૑Ҋ ੽൤ח Animationਸ ҳഅ೧ࠁࣁਃ. Settings

Slide 209

Slide 209 text

animation 11% Settings val panelAnim = SpringAnimation(panelView, DynamicAnimation.TRANSLATION_X) .withSpringForceProperties { dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY stiffness = SpringForce.STIFFNESS_LOW } arrow.setOnClickListener { if (expanded) { panelAnim.animateToFinalPosition(0f) } else { panelAnim.animateToFinalPosition(160.dp) } }

Slide 210

Slide 210 text

animation 11% • LayoutTransition • UiModelী ٮۄ ߡౡ੉ ߸҃غח Animationਸ ҳഅ೧ࠁࣁਃ. Login

Slide 211

Slide 211 text

animation 11% Login

Slide 212

Slide 212 text

animation 11% • ViewPropertyAnimator • Gridী ౠചػ RecyclerView ItemAnimatorܳ ҳഅ೧ࠁࣁਃ. Profile (1)

Slide 213

Slide 213 text

animation 11% Profile (1) class GridItemAnimator(private val spanCount: Int = 1) : DefaultItemAnimator() { override fun animateAddImpl(holder: RecyclerView.ViewHolder) { holder.itemView.animate() .setInterpolator(DecelerateInterpolator()) .setStartDelay(calculateDelay(holder)) .setDuration(addDuration) .alpha(1f) ... .start() } } private fun calculateDelay(holder: ViewHolder): Long { val position = holder.bindingAdapterPosition val order = position / spanCount + position % spanCount return order * addDuration }

Slide 214

Slide 214 text

animation 11% • SharedElements • Viewer ചݶҗ োѾغח ٠ೠ Animationਸ ҳഅ೧ࠁࣁਃ. Profile (2)

Slide 215

Slide 215 text

animation 11% Profile (2) // ProfileActivity.kt val intent = Intent(this, ViewerActivity::class.java) intent.putExtra("resId", resId) val options = ActivityOptionsCompat .makeSceneTransitionAnimation(this, view, view.transitionName) ActivityCompat.startActivity(this, intent, options.toBundle())

Slide 216

Slide 216 text

animation 11% Profile (2) // ViewerActivity.kt override fun onCreate(savedInstanceState: Bundle?) { window.sharedElementEnterTransition = TransitionSet().apply { interpolator = OvershootInterpolator(0.7f) ordering = TransitionSet.ORDERING_TOGETHER addTransition(ChangeBounds().apply { pathMotion = ArcMotion() }) addTransition(ChangeTransform()) addTransition(ChangeClipBounds()) addTransition(ChangeImageTransform()) } super.onCreate(savedInstanceState) ... }

Slide 217

Slide 217 text

animation 11% • Transition • ಫ؊࠶, ಞ૘ ١ ࢚క ੹ജী ٮۄ ۨ੉ইਓ Animationਸ ҳഅ೧ࠁࣁਃ. Viewer

Slide 218

Slide 218 text

animation 11% Viewer val layout = binding.root val constraintSet = ConstraintSet().apply { clone(layout) if (fold) { setGuidelinePercent(R.id.fold_guideline, 0.5f) } else { setGuidelinePercent(R.id.fold_guideline, 1f) } } TransitionManager.beginDelayedTransition(layout) constraintSet.applyTo(layout)

Slide 219

Slide 219 text

animation 11% • AnimationDrawable • ׮਍۽٘ ঌܿী Animation ബҗܳ ୶о೧ࠁࣁਃ. • Tip: AVDب ࢎਊ оמ Notification

Slide 220

Slide 220 text

animation 11% Notification ... Notification.Builder(...) .setSmallIcon(R.drawable.stat_sys_download) ... .build()

Slide 221

Slide 221 text

animation 11% хࢎ೤פ׮!