Slide 1

Slide 1 text

animation 10% animation +10% ௏٘ ৘ઁ: https://github.com/fornewid/android-animation-10p-more

Slide 2

Slide 2 text

안성용 Sungyong An Clova AI Production

Slide 3

Slide 3 text

animation 10% • "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 10% Animationਸ ׮নೞѱ ঌইࠁӝ ݾ಴

Slide 6

Slide 6 text

animation 10% • Drawable Animation • View Animation • Animator • ViewPropertyAnimator • StateListAnimator • CircularReveal animation • Interpolator • DynamicAnimation • Transition • Shared Elements • MotionLayout • 3rd party Library (ex. Lottie) ❌ ❌

Slide 7

Slide 7 text

Animation Drawable

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

animation 10% 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 10% • ױੌ Animationী ৈ۞ ੢੄ ੉޷૑ܳ ࢎਊೠ׮. • ೞ૑݅, • ࠗ٘۞਍ Animationਸ ࠁৈ઱۰ݶ ݆਷ ੉޷૑о ೙ਃೞ׮. (60fps) • ௾ ੉޷૑ܳ ৈ۞੢ ࢎਊೞݶ ݫݽܻ ޙઁо ѣ੿ػ׮. (OOM) ױࣽೠ Frame Animation AnimationDrawable

Slide 15

Slide 15 text

Slide 16

Slide 16 text

animation 10% Drawable Animation A N D R O I D animation +10%

Slide 17

Slide 17 text

animation 10% • AnimationDrawable • AnimatedVectorDrawable • AnimatedStateListDrawable • AnimatedRotateDrawable • AnimatedImageDrawable Animationਸ ૑ਗೞח Drawable Drawable Animation

Slide 18

Slide 18 text

animation 10% • AnimationDrawable • AnimatedVectorDrawable • AnimatedStateListDrawable • AnimatedRotateDrawable • AnimatedImageDrawable Animationਸ ૑ਗೞח Drawable Drawable Animation

Slide 19

Slide 19 text

animation 10% DrawableInflater Link: http://androidxref.com/9.0.0_r3/xref/frameworks/base/graphics/java/android/ graphics/drawable/DrawableInflater.java#148 • res/drawable/{file_name}.xml ... -> AnimatedStateListDrawable -> RippleDrawable -> AnimatedVectorDrawable -> RotateDrawable -> AnimatedRotateDrawable -> AnimationDrawable -> AnimatedImageDrawable ...

Slide 20

Slide 20 text

animation 10% • ੌ߈੸ਵ۽ Drawable Animation਷ द੘/઺૑݅ оמೞ׮. Animatable android.graphics.drawable public interface Animatable { void start(); void stop(); boolean isRunning(); }

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

animation 10% • Notification SmallIcon਷ 24 x 24 ௼ӝܳ ӂ੢ೠ׮. • ૑ਗೞח Drawable ഋध: • AnimationDrawable • AnimatedVectorDrawable • ex) ౵ੌ ׮਍۽٘ ઺ ੌ ٸ, ਑૒੉ח ই੉௑ ಴द ঌܿ ই੉௑ী Animation ಴द Animated Notification Icon Link: ExpandableNotificationRow.java#392 API 21

Slide 23

Slide 23 text

animation 10% • res/drawable/stat_sys_download.xml Animated Notification Icon ...

Slide 24

Slide 24 text

animation 10% • res/drawable/stat_sys_download.xml Animated Notification Icon ...

Slide 25

Slide 25 text

animation 10% Animated Notification Icon NotificationCompat.Builder(...) .setSmallIcon(R.drawable.stat_sys_download) .setContentTitle(...) .setContentText(...) .build()

Slide 26

Slide 26 text

Animated StateList Drawable API 21

Slide 27

Slide 27 text

animation 10% AnimatedStateListDrawable API 21

Slide 28

Slide 28 text

animation 10% AnimatedStateListDrawable API 21 32 32 32 32 32 32 32 32

Slide 29

Slide 29 text

animation 10% AnimatedStateListDrawable API 21

Slide 30

Slide 30 text

animation 10% AnimatedStateListDrawable API 21

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

animation 10% ... AnimatedStateListDrawable API 21

Slide 33

Slide 33 text

animation 10% AnimatedStateListDrawable API 21

Slide 34

Slide 34 text

+ Animated Vector Drawable API 21

Slide 35

Slide 35 text

animation 10% + AnimatedVectorDrawable API 21

Slide 36

Slide 36 text

animation 10% + AnimatedVectorDrawable 0 400 420 570 720 750 950 API 21

Slide 37

Slide 37 text

animation 10% + AnimatedVectorDrawable API 21

Slide 38

Slide 38 text

animation 10% + AnimatedVectorDrawable API 21

Slide 39

Slide 39 text

animation 10% + AnimatedVectorDrawable API 21

Slide 40

Slide 40 text

animation 10% + AnimatedVectorDrawable API 21

Slide 41

Slide 41 text

animation 10% + AnimatedVectorDrawable API 21

Slide 42

Slide 42 text

animation 10% + AnimatedVectorDrawable API 21

Slide 43

Slide 43 text

animation 10%

Slide 44

Slide 44 text

animation 10%

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

animation 10%

Slide 47

Slide 47 text

animation 10%

Slide 48

Slide 48 text

animation 10% android:interpolator="@android:interpolator/linear_out_slow_in"/> + AnimatedVectorDrawable API 21

Slide 49

Slide 49 text

animation 10% + AnimatedVectorDrawable API 21

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

data class HomeUiModel( val isChecked: Boolean ) button.checked = uiModel.isChecked Link: Motional Intelligence: Build Smarter Animations (Google I/O'19)

Slide 52

Slide 52 text

API 21 Ripple Drawable

Slide 53

Slide 53 text

animation 10% RippleDrawable

Slide 54

Slide 54 text

animation 10% RippleDrawable API 21

Slide 55

Slide 55 text

animation 10% RippleDrawable API 21

Slide 56

Slide 56 text

animation 10% RippleDrawable API 21

Slide 57

Slide 57 text

animation 10% RippleDrawable API 21

Slide 58

Slide 58 text

animation 10% RippleDrawable API 21

Slide 59

Slide 59 text

Gradient Drawable

Slide 60

Slide 60 text

animation 10% • ࠄޙ ୐ ߣ૩ ઴ • ࠄޙ ف ߣ૩ ઴ • ࠄޙ ࣁ ߣ૩ ઴ • ࠄޙ ֎ ߣ૩ ઴ • ࠄޙ ׮ࢽ ߣ૩ ઴ GradientDrawable class AnimatedGradientView : View() { private val colors = intArrayOf( Color.RED, Color.GREEN, Color.BLUE ) private val drawable = GradientDrawable( GradientDrawable.Orientation.BR_TL, colors.take(2).toIntArray() ) private val animator = createGradientAnimator() private fun createGradientAnimator(): Animator {

Slide 61

Slide 61 text

animation 10% class AnimatedGradientView : View() { private val colors = intArrayOf( Color.RED, Color.GREEN, Color.BLUE ) private val drawable = GradientDrawable( GradientDrawable.Orientation.BR_TL, colors.take(2).toIntArray() ) private val animator = createGradientAnimator() private fun createGradientAnimator(): Animator { val max = colors.size return ValueAnimator.ofFloat(0f, max.toFloat()).apply { interpolator = LinearInterpolator() duration = 3_000L repeatCount = ValueAnimator.INFINITE GradientDrawable

Slide 62

Slide 62 text

animation 10% ) private val drawable = GradientDrawable( GradientDrawable.Orientation.BR_TL, colors.take(2).toIntArray() ) private val animator = createGradientAnimator() private fun createGradientAnimator(): Animator { val max = colors.size return ValueAnimator.ofFloat(0f, max.toFloat()).apply { interpolator = LinearInterpolator() duration = 3_000L repeatCount = ValueAnimator.INFINITE repeatMode = ValueAnimator.RESTART val evaluator = ArgbEvaluator() addUpdateListener { val index = (it.animatedValue as Float).toInt() val start = colors[index % max] val center = colors[(index + 1) % max] val end = colors[(index + 2) % max] GradientDrawable

Slide 63

Slide 63 text

animation 10% private fun createGradientAnimator(): Animator { val max = colors.size return ValueAnimator.ofFloat(0f, max.toFloat()).apply { interpolator = LinearInterpolator() duration = 3_000L repeatCount = ValueAnimator.INFINITE repeatMode = ValueAnimator.RESTART val evaluator = ArgbEvaluator() addUpdateListener { val index = (it.animatedValue as Float).toInt() val start = colors[index % max] val center = colors[(index + 1) % max] val end = colors[(index + 2) % max] val fraction = it.animatedValue as Float - index drawable.colors = intArrayOf( evaluator.evaluate(fraction, start, center) as Int, evaluator.evaluate(fraction, center, end) as Int ) } } } GradientDrawable

Slide 64

Slide 64 text

animation 10% private fun createGradientAnimator(): Animator { val max = colors.size return ValueAnimator.ofFloat(0f, max.toFloat()).apply { interpolator = LinearInterpolator() duration = 3_000L repeatCount = ValueAnimator.INFINITE repeatMode = ValueAnimator.RESTART val evaluator = ArgbEvaluator() addUpdateListener { val index = (it.animatedValue as Float).toInt() val start = colors[index % max] val center = colors[(index + 1) % max] val end = colors[(index + 2) % max] val fraction = it.animatedValue as Float - index drawable.colors = intArrayOf( evaluator.evaluate(fraction, start, center) as Int, evaluator.evaluate(fraction, center, end) as Int ) } } } GradientDrawable API 16

Slide 65

Slide 65 text

animation 10% drawable.colors = intArrayOf( evaluator.evaluate(fraction, start, center) as Int, evaluator.evaluate(fraction, center, end) as Int ) } } } init { background = drawable // Animation द੘ animator.start() // Animation ઺૑ animator.cancel() } } GradientDrawable API 16

Slide 66

Slide 66 text

animation 10% view.clipToOutline = true view.outlineProvider = OvalOutlineProvider object OvalOutlineProvider : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { outline.setOval( view.paddingLeft, view.paddingTop, view.width - view.paddingRight, view.height - view.paddingBottom ) } } GradientDrawable API 21

Slide 67

Slide 67 text

animation 10% view.clipToOutline = true view.outlineProvider = RoundRectOutlineProvider(clipRadius) class RoundRectOutlineProvider( private val radius: Float ) : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { outline.setRoundRect( view.paddingLeft, view.paddingTop, view.width - view.paddingRight, view.height - view.paddingBottom, radius ) } GradientDrawable API 21

Slide 68

Slide 68 text

animation 10% class AnimatedBorderView : View() { private var borderWidth: Int = ... override fun draw(canvas: Canvas) { canvas.clipBorder(borderWidth) super.draw(canvas) } private fun Canvas.clipBorder(gap: Int) { val rect = Rect(gap, gap, width - gap, height - gap) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { clipOutRect(rect) } else { clipRect(rect, Region.Op.DIFFERENCE) GradientDrawable

Slide 69

Slide 69 text

animation 10% private var borderWidth: Int = ... override fun draw(canvas: Canvas) { canvas.clipBorder(borderWidth) super.draw(canvas) } private fun Canvas.clipBorder(gap: Int) { val rect = Rect(gap, gap, width - gap, height - gap) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { clipOutRect(rect) } else { clipRect(rect, Region.Op.DIFFERENCE) } } } GradientDrawable

Slide 70

Slide 70 text

animation 10% override fun draw(canvas: Canvas) { canvas.clipOuter(clipPath) super.draw(canvas) } private fun Canvas.clipOuter(path: Path) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { clipOutPath(path) } else { clipPath(path, Region.Op.DIFFERENCE) } } GradientDrawable

Slide 71

Slide 71 text

animation 10% override fun draw(canvas: Canvas) { canvas.clipInner(clipPath) super.draw(canvas) } private fun Canvas.clipOuter(path: Path) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { clipPath(path) } else { clipPath(path, Region.Op.INTERSECT) } } GradientDrawable

Slide 72

Slide 72 text

animation 10% Lottie APNG 3rd Party

Slide 73

Slide 73 text

animation 10% • ٣੗੉ցо ખ ؊ ੗ਬ܂ѱ Ѿҗޛਸ ੘সೡ ࣻ ੓׮. • Android, iOS, Web ݽف زੌೞѱ ૑ਗೠ׮. • ױ, Vector ӝ߈੉޲۽ Gradationਸ ੸ਊೡ ࣻ হ׮. Render Adobe After Effects animations! Lottie Drawable Link: https://github.com/airbnb/lottie-android animation 10% 3rd Party

Slide 74

Slide 74 text

animation 10% • res/layout/fragment_third_party.xml LottieDrawable 3rd Party

Slide 75

Slide 75 text

animation 10% • PNGܳ ഛ੢ೠ ੉޷૑ ౵ੌ ನݘ (.png, .apng) • ৈ۞ ੢੄ PNG ੉޷૑ܳ ೞա۽ ೤ೠ ഋక׮. • Gradation ৈࠗী ࢚ҙহ੉ Animation оמೞ׮. • ױ, AnimationDrawable୊ۢ ݫݽܻ৬ FPS ޙઁо ੓׮. Animated Portable Network Graphics APNG Link: https://ko.wikipedia.org/wiki/APNG 3rd Party

Slide 76

Slide 76 text

animation 10% • ImageView ١੄ Drawable APIী ࢎਊೡ ࣻ ੓׮. • ইऔѱب View ҳഅ୓ח ઁҕغ૑ ঋח׮. A lightweight and fast APNG image decoder for Android ApngDrawable Link: https://github.com/line/apng-drawable 3rd Party

Slide 77

Slide 77 text

animation 10% ApngDrawable // WorkerThread val apngDrawable: ApngDrawable = ApngDrawable.decode(context.resources, resId).apply { loopCount = ApngDrawable.LOOP_FOREVER setTargetDensity(resources.displayMetrics) } // MainThread setImageDrawable(apngDrawable) 3rd Party

Slide 78

Slide 78 text

animation 10% • res/layout/fragment_third_party.xml ApngImageView Custom Link: https://github.com/fornewid/android-animation-10p-more/commit/b2657ce225

Slide 79

Slide 79 text

animation 10% Progress Bar Rotate Drawable

Slide 80

Slide 80 text

animation 10% ProgressBar + RotateDrawable

Slide 81

Slide 81 text

animation 10% ProgressBar + RotateDrawable

Slide 82

Slide 82 text

animation 10% ProgressBar + RotateDrawable

Slide 83

Slide 83 text

animation 10% ProgressBar + RotateDrawable

Slide 84

Slide 84 text

animation 10% ProgressBar + RotateDrawable

Slide 85

Slide 85 text

animation 10% Progress Bar Clip Drawable

Slide 86

Slide 86 text

animation 10% ProgressBar + ClipDrawable

Slide 87

Slide 87 text

animation 10% ProgressBar + ClipDrawable

Slide 88

Slide 88 text

animation 10% ProgressBar + ClipDrawable

Slide 89

Slide 89 text

animation 10% ProgressBar + ClipDrawable

Slide 90

Slide 90 text

animation 10% Animator Drawable Level

Slide 91

Slide 91 text

animation 10% • Drawable਷ Level ӝמ੉ ੓׮. (ߧਤ: 0 ~ 10000) • ClipDrawable, RotateDrawable, ScaleDrawable, LevelListDrawable ١ • Drawable#setLevel(int) API • ImageView#setImageLevel(int) API Drawableҗ Ѿ೤ೞৈ ࣚऔѱ Animation ҳഅ оמ Animator + Drawable Level

Slide 92

Slide 92 text

animation 10% Animator + Drawable Level private val animator = ValueAnimator.ofFloat(0f, 1f).apply { repeatMode = ValueAnimator.REVERSE repeatCount = ValueAnimator.INFINITE duration = 1_000L interpolator = Interpolators.LINEAR addUpdateListener { batteryClip.setImageLevel( (it.animatedFraction * 10000).toInt()) } }

Slide 93

Slide 93 text

animation 10% Animator A N D R O I D animation +10%

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

animation 10% 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 96

Slide 96 text

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

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

animation 10% 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 103

Slide 103 text

animation 10% 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 104

Slide 104 text

animation 10% ... } 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 105

Slide 105 text

animation 10% 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 106

Slide 106 text

animation 10% 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 107

Slide 107 text

Animator

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

animation 10% Animator

Slide 110

Slide 110 text

animation 10% Animator

Slide 111

Slide 111 text

animation 10% Animator floatType intType pathType colorType

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

animation 10% Animator

Slide 115

Slide 115 text

animation 10% Animator

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

animation 10% 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 119

Slide 119 text

animation 10% updateUi(it.animatedFraction) Animator

Slide 120

Slide 120 text

animation 10% 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 121

Slide 121 text

animation 10% rotation = lerp(0f, 360f, fraction) Animator

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

Lerp + Constraint Layout Custom

Slide 124

Slide 124 text

animation 10% ... Lerp + ConstraintLayout

Slide 125

Slide 125 text

animation 10% class CollapsingConstraintLayout : ConstraintLayout(), AppBarLayout.OnOffsetChangedListener { override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) { setProgress(-verticalOffset / appBarLayout.totalScrollRange.toFloat()) } private fun setProgress(progress: Float) { val fraction = progress.coerceIn(0f, 1f) children.forEach { if (it is ProgressHelper) { it.setProgress(fraction) } } } ... Lerp + ConstraintLayout

Slide 126

Slide 126 text

animation 10% class Alpha : ConstraintHelper(), ProgressHelper { override fun setProgress(progress: Float) { ... views.forEach { it.alpha = lerp(0f, 1f, 1f - progress) } } ... Lerp + ConstraintLayout

Slide 127

Slide 127 text

Layout
 Transition API 11

Slide 128

Slide 128 text

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

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

animation 10% 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 API 11

Slide 131

Slide 131 text

animation 10% 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 API 11

Slide 132

Slide 132 text

Circular Reveal API 21, 14

Slide 133

Slide 133 text

animation 10% Circular Reveal API 21

Slide 134

Slide 134 text

animation 10% // 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 API 21

Slide 135

Slide 135 text

animation 10% 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 API 21

Slide 136

Slide 136 text

animation 10% 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 API 21

Slide 137

Slide 137 text

animation 10% MDC Circular Reveal API 14

Slide 138

Slide 138 text

animation 10% 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 MDC Circular Reveal API 14

Slide 139

Slide 139 text

animation 10% 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 API 21

Slide 140

Slide 140 text

animation 10% private inline fun CircularRevealWidget.createCircularRevealCompatOf( target: View, startRadius: Float, endRadius: Float, block: Animator.() -> Unit ): Animator { return CircularRevealCompat.createCircularReveal( this, target.centerX().toFloat(), target.centerY().toFloat(), startRadius, endRadius ).apply(block) } MDC Circular Reveal API 14

Slide 141

Slide 141 text

FAB
 Transform Custom

Slide 142

Slide 142 text

animation 10% FAB Transform // Show transformFab.isExpanded = true // Hide transformFab.isExpanded = false

Slide 143

Slide 143 text

animation 10% ... FAB Transform

Slide 144

Slide 144 text

animation 10% ... FAB Transform

Slide 145

Slide 145 text

StateList
 Animator API 21

Slide 146

Slide 146 text

animation 10% StateListAnimator

Slide 147

Slide 147 text

animation 10% StateListAnimator

Slide 148

Slide 148 text

animation 10% StateListAnimator

Slide 149

Slide 149 text

animation 10% StateListAnimator

Slide 150

Slide 150 text

animation 10% StateListAnimator

Slide 151

Slide 151 text

StateList
 Animator + Transition API 21

Slide 152

Slide 152 text

animation 10% StateListAnimator + Transition

Slide 153

Slide 153 text

animation 10% StateListAnimator + Transition itemView.isActivated = expand

Slide 154

Slide 154 text

animation 10% StateListAnimator + Transition

Slide 155

Slide 155 text

animation 10% StateListAnimator + Transition

Slide 156

Slide 156 text

animation 10% android:valueFrom="@color/android1" android:valueTo="@color/android4" android:valueType="colorType" /> StateListAnimator + Transition

Slide 157

Slide 157 text

animation 10% StateListAnimator + Transition itemView.isActivated = expand

Slide 158

Slide 158 text

animation 10% ... itemView.isActivated = expand StateListAnimator + Transition

Slide 159

Slide 159 text

animation 10% android:id="@+id/actionGroup" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" app:constraint_referenced_ids="add,close,touchApp" /> TransitionManager.beginDelayedTransition(container) itemView.isActivated = expand actionGroup.isVisible = expand StateListAnimator + Transition

Slide 160

Slide 160 text

animation 10% Interpolator A N D R O I D animation +10%

Slide 161

Slide 161 text

Interpolator

Slide 162

Slide 162 text

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

Slide 163

Slide 163 text

animation 10% 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 164

Slide 164 text

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

Slide 165

Slide 165 text

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

Slide 166

Slide 166 text

animation 10% PathInterpolator android.view.animation API 21

Slide 167

Slide 167 text

animation 10% 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 168

Slide 168 text

animation 10% 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 169

Slide 169 text

animation 10% Link: https://easings.net/ Easing Interpolator Custom

Slide 170

Slide 170 text

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

Slide 171

Slide 171 text

animation 10% 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 172

Slide 172 text

animation 10% • ೙ਃೠ ҃਋, Custom Viewী Attributeܳ ୶оೞৈ
 Layout XMLী Interpolatorܳ ࢶ঱ೞח ߑߨ੉ оמೞ׮. Interpolator Attribute

Slide 173

Slide 173 text

animation 10% Interpolator Attribute init { val a: TypedArray = ... val resId = a.getResourceId( R.styleable.CustomView_interpolator, 0) if (resId > 0) { ... = AnimationUtils.loadInterpolator(context, resId) } ... }

Slide 174

Slide 174 text

animation 10% Interpolator Attribute

Slide 175

Slide 175 text

animation 10% ViewPropertyAnimator A N D R O I D animation +10%

Slide 176

Slide 176 text

View
 Property Animator API 12

Slide 177

Slide 177 text

animation 10% ViewPropertyAnimator view.animate() // ViewPropertyAnimator

Slide 178

Slide 178 text

animation 10% ViewPropertyAnimator view.animate() .translationX(100f)

Slide 179

Slide 179 text

animation 10% ViewPropertyAnimator view.animate() .translationX(100f) .setStartDelay(300L) // ms .setDuration(1000L) // ms .setInterpolator(Interpolators.ACCELERATE_DECELERATE)

Slide 180

Slide 180 text

animation 10% ViewPropertyAnimator view.animate() .translationX(100f) .translationY(50f) .rotation(90f) .scaleX(1.5f) .scaleY(0.5f) .alpha(1f)

Slide 181

Slide 181 text

animation 10% ViewPropertyAnimator view.animate().cancel() view.translationX = 0f view.animate() .translationX(100f)

Slide 182

Slide 182 text

animation 10% ViewPropertyAnimator view.animate().cancel() view.translationX = currentTranslationX view.animate() .translationX(100f)

Slide 183

Slide 183 text

animation 10% ViewPropertyAnimator view.animate().cancel() view.translationX = view.translationX view.animate() .translationX(100f)

Slide 184

Slide 184 text

animation 10% ViewPropertyAnimator view.animate().cancel() // view.translationX = view.translationX view.animate() .translationX(100f)

Slide 185

Slide 185 text

animation 10% ViewPropertyAnimator view.animate() .translationX(100f) .withLayer() ❓ API 16

Slide 186

Slide 186 text

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

Slide 187

Slide 187 text

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

Slide 188

Slide 188 text

animation 10% Hardware Layer API 11 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 189

Slide 189 text

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

Slide 190

Slide 190 text

animation 10% • 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 191

Slide 191 text

animation 10% View#hasOverlappingRendering() API 16

Slide 192

Slide 192 text

animation 10% View#hasOverlappingRendering() API 16

Slide 193

Slide 193 text

animation 10% View#hasOverlappingRendering() API 16

Slide 194

Slide 194 text

animation 10% View#hasOverlappingRendering() API 16

Slide 195

Slide 195 text

animation 10% View#hasOverlappingRendering() API 16

Slide 196

Slide 196 text

animation 10% View#hasOverlappingRendering() API 16

Slide 197

Slide 197 text

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

Slide 198

Slide 198 text

animation 10% RecyclerView ItemAnimator Custom

Slide 199

Slide 199 text

animation 10% RecyclerView.ItemAnimator recyclerView.itemAnimator = SlideInUpAnimator()

Slide 200

Slide 200 text

animation 10% RecyclerView.ItemAnimator class SlideInUpAnimator : DefaultItemAnimator() { override fun animateAddImpl(holder: RecyclerView.ViewHolder) { holder.itemView.animate() .translationY(0f) .alpha(1f) .setDuration(addDuration) .start() } }

Slide 201

Slide 201 text

animation 10% RecyclerView.ItemAnimator recyclerView.itemAnimator = SlideInUpAnimator() recyclerView.adapter = RecyclerViewAdapter() .apply { submitList(list) }

Slide 202

Slide 202 text

animation 10% RecyclerView.ItemAnimator class RecyclerViewAdapter() : ListAdapter( IdBasedDiffCallback { id.toString() } ) { ... } class IdBasedDiffCallback( private val id: T.() -> String ) : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: T, newItem: T): Boolean { return oldItem.id() == newItem.id() } ... }

Slide 203

Slide 203 text

animation 10% recyclerview-animators Link: https://github.com/wasabeef/recyclerview-animators 3rd Party

Slide 204

Slide 204 text

animation 10% View Animation A N D R O I D animation +10%

Slide 205

Slide 205 text

View Animation

Slide 206

Slide 206 text

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

Slide 207

Slide 207 text

animation 10% View Animation

Slide 208

Slide 208 text

animation 10% View Animation

Slide 209

Slide 209 text

animation 10% View Animation

Slide 210

Slide 210 text

animation 10% View Animation

Slide 211

Slide 211 text

animation 10% View Animation

Slide 212

Slide 212 text

animation 10% View Animation

Slide 213

Slide 213 text

animation 10% View Animation

Slide 214

Slide 214 text

Window Animation

Slide 215

Slide 215 text

animation 10% Window Animation: Activity activity.overridePendingTransition( R.anim.slide_in_right, // enterAnim R.anim.slide_out_left // exitAnim ) activity.overridePendingTransition( R.anim.slide_in_left, // popEnterAnim R.anim.slide_out_right // popExitAnim )

Slide 216

Slide 216 text

animation 10% Window Animation: Fragment fragmentManager.beginTransaction() .setCustomAnimations( R.anim.slide_in_right, // enterAnim R.anim.slide_out_left, // exitAnim R.anim.slide_in_left, // popEnterAnim R.anim.slide_out_right // popExitAnim ) .replace(...) .commit()

Slide 217

Slide 217 text

animation 10% Window Animation: Navigation

Slide 218

Slide 218 text

animation 10% DynamicAnimation A N D R O I D animation +10%

Slide 219

Slide 219 text

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

Slide 220

Slide 220 text

Fling Animation

Slide 221

Slide 221 text

animation 10% FlingAnimation FlingAnimation(view, DynamicAnimation.TRANSLATION_X) .setStartVelocity(5000f) .setFriction(1f) .setMinValue(0f) .setMaxValue(1920f) .start() Link: https://github.com/simonnorberg/fling-animation-demo

Slide 222

Slide 222 text

animation 10% DynamicAnimation.ViewProperty ViewProperty TRANSLATION_X = new ViewProperty("translationX") ViewProperty TRANSLATION_Y = new ViewProperty("translationY") ViewProperty TRANSLATION_Z = new ViewProperty("translationZ") ViewProperty SCALE_X = new ViewProperty("scaleX") ViewProperty SCALE_Y = new ViewProperty("scaleY") ViewProperty ROTATION = new ViewProperty("rotation") ViewProperty ROTATION_X = new ViewProperty("rotationX") ViewProperty ROTATION_Y = new ViewProperty("rotationY") ViewProperty X = new ViewProperty("x") ViewProperty Y = new ViewProperty("y") ViewProperty Z = new ViewProperty("z") ViewProperty ALPHA = new ViewProperty("alpha") ViewProperty SCROLL_X = new ViewProperty("scrollX") ViewProperty SCROLL_Y = new ViewProperty("scrollY")

Slide 223

Slide 223 text

Spring Animation

Slide 224

Slide 224 text

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

Slide 225

Slide 225 text

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

Slide 226

Slide 226 text

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

Slide 227

Slide 227 text

animation 10% 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 228

Slide 228 text

animation 10% 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 229

Slide 229 text

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

Slide 230

Slide 230 text

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

Slide 231

Slide 231 text

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

Slide 232

Slide 232 text

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

Slide 233

Slide 233 text

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

Slide 234

Slide 234 text

animation 10% fun View.spring( property: ViewProperty, stiffness: Float = 500f, damping: Float = SpringForce.DAMPING_RATIO_NO_BOUNCY, startVelocity: Float? = null ): SpringAnimation { val key = getKey(property) var springAnim = getTag(key) as? SpringAnimation? if (springAnim == null) { springAnim = SpringAnimation(this, property) setTag(key, springAnim) } springAnim.spring = (springAnim.spring ?: SpringForce()).apply { this.dampingRatio = damping this.stiffness = stiffness SpringAnimation

Slide 235

Slide 235 text

animation 10% fun View.spring( property: ViewProperty, stiffness: Float = 500f, damping: Float = SpringForce.DAMPING_RATIO_NO_BOUNCY, startVelocity: Float? = null ): SpringAnimation { val key = getKey(property) var springAnim = getTag(key) as? SpringAnimation? if (springAnim == null) { springAnim = SpringAnimation(this, property) setTag(key, springAnim) } springAnim.spring = (springAnim.spring ?: SpringForce()).apply { this.dampingRatio = damping this.stiffness = stiffness } startVelocity?.let { springAnim.setStartVelocity(it) } return springAnim } SpringAnimation

Slide 236

Slide 236 text

animation 10% stiffness: Float = 500f, damping: Float = SpringForce.DAMPING_RATIO_NO_BOUNCY, startVelocity: Float? = null ): SpringAnimation { val key = getKey(property) var springAnim = getTag(key) as? SpringAnimation? if (springAnim == null) { springAnim = SpringAnimation(this, property) setTag(key, springAnim) } springAnim.spring = (springAnim.spring ?: SpringForce()).apply { this.dampingRatio = damping this.stiffness = stiffness } startVelocity?.let { springAnim.setStartVelocity(it) } return springAnim } SpringAnimation Link: https://github.com/android/plaid/.../SpringUtils.kt#L31

Slide 237

Slide 237 text

animation 10% ViewPropertyAnimator view.animate() .translationX(100f)

Slide 238

Slide 238 text

animation 10% SpringAnimation view.spring(TRANSLATION_X) .animateToFinalPosition(100f)

Slide 239

Slide 239 text

animation 10% view.animate() .translationX(100f) .translationY(100f) ViewPropertyAnimator

Slide 240

Slide 240 text

animation 10% SpringAnimation view.spring(TRANSLATION_X) .animateToFinalPosition(100f) view.spring(TRANSLATION_Y) .animateToFinalPosition(100f)

Slide 241

Slide 241 text

RecyclerView Spring ItemAnimator

Slide 242

Slide 242 text

animation 10% class SpringItemAnimator : DefaultItemAnimator() { override fun animateMove(...): Boolean { val view = holder.itemView val fromX = fromViewX + holder.itemView.translationX.toInt() val fromY = fromViewY + holder.itemView.translationY.toInt() endAnimation(holder) val deltaX = toViewX - fromX val deltaY = toViewY - fromY ... if (deltaX != 0) { view.translationX = (-deltaX).toFloat() } if (deltaY != 0) { view.translationY = (-deltaY).toFloat() } SpringItemAnimator

Slide 243

Slide 243 text

animation 10% override fun animateMove(...): Boolean { val view = holder.itemView val fromX = fromViewX + holder.itemView.translationX.toInt() val fromY = fromViewY + holder.itemView.translationY.toInt() endAnimation(holder) val deltaX = toViewX - fromX val deltaY = toViewY - fromY ... if (deltaX != 0) { view.translationX = (-deltaX).toFloat() } if (deltaY != 0) { view.translationY = (-deltaY).toFloat() } pendingMoves.add(holder) return true } override fun runPendingAnimations() { super.runPendingAnimations() SpringItemAnimator

Slide 244

Slide 244 text

animation 10% if (deltaY != 0) { view.translationY = (-deltaY).toFloat() } pendingMoves.add(holder) return true } override fun runPendingAnimations() { super.runPendingAnimations() ... if (pendingMoves.isNotEmpty()) { for (i in pendingMoves.indices.reversed()) { moveItem(pendingMoves.removeAt(i)) } } } private fun moveItem(holder: RecyclerView.ViewHolder) { val springX = holder.itemView.spring(TRANSLATION_X) val springY = holder.itemView.spring(TRANSLATION_Y) ... SpringItemAnimator

Slide 245

Slide 245 text

animation 10% if (pendingMoves.isNotEmpty()) { for (i in pendingMoves.indices.reversed()) { moveItem(pendingMoves.removeAt(i)) } } } private fun moveItem(holder: RecyclerView.ViewHolder) { val springX = holder.itemView.spring(TRANSLATION_X) val springY = holder.itemView.spring(TRANSLATION_Y) ... springX.animateToFinalPosition(0f) springY.animateToFinalPosition(0f) ... } } SpringItemAnimator Link: https://github.com/android/plaid/.../SlideInItemAnimator.kt

Slide 246

Slide 246 text

animation 10% Transition Animation A N D R O I D animation +10%

Slide 247

Slide 247 text

Transition API 19

Slide 248

Slide 248 text

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

Slide 249

Slide 249 text

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

Slide 250

Slide 250 text

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

Slide 251

Slide 251 text

animation 10% 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 252

Slide 252 text

animation 10% Transition =

Slide 253

Slide 253 text

animation 10% 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 254

Slide 254 text

animation 10% • 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 255

Slide 255 text

Shared Elements API 21

Slide 256

Slide 256 text

animation 10% 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 257

Slide 257 text

animation 10% 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 258

Slide 258 text

animation 10% Shared Elements: Navigation // Navigation: Between activities val extras = ActivityNavigatorExtras( ActivityOptionsCompat.makeSceneTransitionAnimation( activity, Pair.create(view, view.transitionName) ) ) findNavController().navigate(actionToDetail(), extras) // Navigation: Between fragments val extras = FragmentNavigatorExtras( view to view.transitionName ) findNavController().navigate(actionToDetail(), extras)

Slide 259

Slide 259 text

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

Slide 260

Slide 260 text

animation 10% Shared Elements

Slide 261

Slide 261 text

animation 10% Shared Elements

Slide 262

Slide 262 text

animation 10% 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 263

Slide 263 text

Ugly Shared Elements

Slide 264

Slide 264 text

animation 10% 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 265

Slide 265 text

animation 10% Shared Elements class MasterFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) exitTransition = ...(R.transition.move) reenterTransition = ...(R.transition.move) } } class DetailFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enterTransition = ...(R.transition.move) returnTransition = ...(R.transition.move) sharedElementEnterTransition = ...(R.transition.move_shared_element) sharedElementReturnTransition = ...(R.transition.move_shared_element) } }

Slide 266

Slide 266 text

animation 10% Shared Elements

Slide 267

Slide 267 text

animation 10% Shared Elements

Slide 268

Slide 268 text

animation 10% Shared Elements

Slide 269

Slide 269 text

animation 10% Shared Elements

Slide 270

Slide 270 text

animation 10% • ߸ചೞח ੉޷૑ • Drawable Animation • CustomView + Animator
 • ਑૒੉ח ױੌ ੉޷૑ • ViewPropertyAnimator • DynamicAnimation Summary Link: https://github.com/fornewid/android-animation-10p-more • ೣԋ ਑૒੉ח ੉޷૑ٜ • Animator (+ lerp) • Transition
 • ചݶ ੹ജ • View Animation • Transition (+ SharedElements)

Slide 271

Slide 271 text

animation 10% • https://developer.android.com/training/animation • ⚽ https://github.com/android/animation • https://github.com/android/plaid • https://github.com/google/iosched • Android Performance Patterns References

Slide 272

Slide 272 text

animation 10% Q & A A N D R O I D animation +10%