SlideShare a Scribd company logo
The world of
Android Animations
+Nelson Glauber
@nglauber
www.nglauber.com.br
Por que animações?
Animations!
• No mundo real coisas não aparecem “do nada”, elas
se movimentam
• O olho humano é sensível ao movimento e isso
pode ajudar o usuário a entender melhor seu
aplicativo
• Pense na sua aplicação como um palco onde a
informação entra e sai do palco de maneira
coordenada.
https://developer.android.com/design/get-started/principles.html
1ª geração de
animações
View Animations
<alpha
android:duration="1000"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
val alphaAnim = AnimationUtils.loadAnimation(

context, R.anim.my_animation);
imageView.startAnimation(anim);
val alphaAnim = AlphaAnimation(1f, 0f)
alphaAnim.duration = 1000
imageView.startAnimation(alphaAnim)
res/anim/my_animation.xml
val anim = RotateAnimation(
0, 360,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f)
anim.duration = 1000
imageView.startAnimation(anim)
<rotate
android:duration="1000"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%" />
val anim = ScaleAnimation(1, 3, 1, 3,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f)
anim.duration = 1000
myView.startAnimation(anim)
<scale
android:duration="1000"
android:fromXScale="1.0"
android:toXScale="3.0"
android:fromYScale="1.0"
android:toYScale="3.0"
android:pivotX="50%"
android:pivotY="50%" />
Não corte sua animação!
<ViewGroup
...
android:clipChildren="false"
android:clipToPadding="false" />
val anim = TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0f,
Animation.RELATIVE_TO_SELF, 1.0f,
Animation.RELATIVE_TO_SELF, 0f,
Animation.RELATIVE_TO_SELF, 2.0f)
anim.duration = 1000
myView.startAnimation(anim)
<translate
android:duration="1000"
android:fromXDelta="0"
android:toXDelta="100%"
android:fromYDelta="0"
android:toYDelta="200%" />
Combinando animações
val animationSet = AnimationSet(true)
animationSet.addAnimation(rotate)
animationSet.addAnimation(alpha)
animationSet.addAnimation(scale)
animationSet.addAnimation(translate)
animationSet.setDuration(1000)
myView.startAnimation(animationSet)
<set android:duration="1000">
<rotate ... />
<alpha ... />
<scale ... />
<translate ... />
</set>
val interpolator = …
LinearInterpolator()
AccelerateDecelerateInterpolator()
BounceInterpolator()
AccelerateInterpolator(1.0f) // factor (optional)
AnticipateInterpolator(2.0f) // <- tension (optional)
// tension, extra tension (optional)
AnticipateOvershootInterpolator(2.0f, 1.5f)
CycleInterpolator(2f) // <- cycles
DecelerateInterpolator(1.0f) // <- factor (optional)
OvershootInterpolator(2.0f) // <- tension (optional)
FastOutLinearInInterpolator()

FastOutSlowInInterpolator()

LinearOutSlowInInterpolator()
anim.interpolator = interpolator
<translate ...
android:interpolator="@android:anim/overshoot_interpolator"/>
Interpolator class Resource ID
LinearInterpolator @android:anim/linear_interpolator
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator
BounceInterpolator @android:anim/bounce_interpolator
AccelerateInterpolator @android:anim/accelerate_interpolator
AnticipateInterpolator @android:anim/anticipate_interpolator
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator
DecelerateInterpolator @android:anim/decelerate_interpolator
OvershootInterpolator @android:anim/overshoot_interpolator
FastOutLinearInInterpolator	 @interpolator/fast_out_linear_in	(support)	
FastOutSlowInInterpolator	 @interpolator/fast_out_slow_in	(support)	
LinearOutSlowInInterpolator	 @interpolator/linear_out_slow_in	(suppport)
val anim = // Qualquer animação…
anim.setAnimationListener(object : AnimationListener {
override fun onAnimationStart(animation: Animation) {
}
override fun onAnimationRepeat(animation: Animation) {
}
override fun onAnimationEnd(animation: Animation) {
}
})
anim.fillBefore = false
anim.fillAfter = true
anim.repeatCount = 1
anim.repeatMode = Animation.REVERSE // INFINITE or RESTART
myView.startAnimation(anim)
Animando a mudança de Activity
Animando a mudança de Activity
val it = Intent(this, NewActivity::class.java)
startActivity(it)
overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim)
override fun onBackPressed() {
super.onBackPressed()
overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim)
}
Animação quadro-a-quadro
<animation-list ...
android:oneshot="false">
<item android:drawable=“@drawable/mario_0"
android:duration="100" />
<item android:drawable=“@drawable/mario_1"
android:duration="100" />
<item android:drawable=“@drawable/mario_2"
android:duration="100" />
...
</animation-list>
res/drawable/sprite.xml
Imagem: https://rawgit.com/Grafluxe/sequence-runner/master/sample/index.html
Animação quadro-a-quadro
val sprite = … // ImageView
sprite.setBackgroundResource(R.drawable.sprite)
val spriteAnimation = sprite.background as AnimationDrawable
if (spriteAnimation.isRunning){
spriteAnimation.stop()
} else {
spriteAnimation.start()
}
Imagem: https://rawgit.com/Grafluxe/sequence-runner/master/sample/index.html
Prós e contras…
• Prós
• Simples de usar
• Disponível em todas as versões do Android
• Contras
• Muito limitado
• Não altera a posição real da view 😱
2ª geração de
animações
View Property
Animator
Property Animations
• Disponível a partir do Android 3.0 (v11)
• Simples e fácil de usar
• Você pode animar várias propriedades usando
simplesmente o método animate() da view (v12).
view.animate()
.alpha(0)
.translationX(-view.getHeight())
.translationY(-view.getWidth())
.scaleX(2f)
.scaleY(2f)
.rotation(360)
.setInterpolator(LinearInterpolator())
.withStartAction(Runnable {
// animation's started
})
.withEndAction(Runnable {
// animation's finished
})
.setDuration(1000)
.setStartDelay(1000)
.start()
Property Animations
Animator
AnimatorSet ValueAnimator
ObjectAnimator
Podemos animar qualquer
propriedade utilizando as classes:
val alpha = ObjectAnimator.ofFloat(view, View.ALPHA, 0f)
alpha.repeatMode = ValueAnimator.REVERSE
alpha.repeatCount = 1
val animXml = AnimatorInflater.loadAnimator(
this, R.animator.anim_fade)
animXml.setTarget(imgBazinga)
res/animator/anim_fade.xml
<objectAnimator xmlns:android="..."
android:duration="1000"
android:propertyName="alpha"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType" />
val scaleX = ObjectAnimator.ofFloat(
view, View.SCALE_X, 2f)
val scaleY = ObjectAnimator.ofFloat(
view, View.SCALE_Y, 2f)
val transl = ObjectAnimator.ofFloat(
view, View.TRANSLATION_X, -view.getWidth())
val rotate = ObjectAnimator.ofFloat(
view, View.ROTATION, 360f)
val alpha = ObjectAnimator.ofFloat(
view, View.ALPHA, 0f)
val animatorSet = AnimatorSet()
animatorSet.play(scaleX)
.with(scaleY)
.with(transl)
animatorSet.play(rotate)
.with(alpha)
.after(transl)
animatorSet.duration = 2000
animatorSet.start()
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(2000);
// Sequentially
animatorSet.playSequentially(
scaleX, scaleY, transl, rotate, alpha);
// or Together
animatorSet.playTogether(
scaleX, scaleY, transl, rotate, alpha);
animatorSet.start();
<set xmlns:android=“…”
android:ordering="together">
<objectAnimator
android:duration="1000"
android:propertyName="scaleX"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="1"
android:valueTo="2"
android:valueType="floatType" />
<objectAnimator
android:duration="1000"
android:propertyName="scaleY"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="1"
android:valueTo="2"
android:valueType="floatType" />
</set>
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationCancel(animation: Animator) {
super.onAnimationCancel(animation)
}
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
}
override fun onAnimationRepeat(animation: Animator) {
super.onAnimationRepeat(animation)
}
override fun onAnimationStart(animation: Animator) {
super.onAnimationStart(animation)
}
override fun onAnimationPause(animation: Animator) {
super.onAnimationPause(animation)
}
override fun onAnimationResume(animation: Animator) {
super.onAnimationResume(animation)
}
})
Property Animations
<<interface>>

TypeEvaluator<T>
IntEvaluator
ArgbEvaluator
FloatEvaluator
Podemos utilizar os evaluators existentes
para calcular o valores das propriedades:
ObjectAnimator.ofObject(textView,
"textColor",
ArgbEvaluator(),
textView.currentTextColor,
Color.RED).start()
Animate Layout changes
<LinearLayout
...
android:animateLayoutChanges="true" />
API Level 11
3ª geração de
animações
Scenes & Transitions
• Introduzida no Android 4.4. KitKat (API Level 19)
• Captura o estado de cada view da cena e anima
para o estado da próxima cena
val sceneMore = Scene.getSceneForLayout(
sceneRoot, R.layout.scene_more, context)
val sceneLess = Scene.getSceneForLayout(
sceneRoot, R.layout.scene_less, context)
TransitionManager.go(if (more) sceneMore else sceneLess,
AutoTransition())
// reset views and events 😢
Transitions
• From API 19
• Fade
• AutoTransition
• ChangeBounds
• TransitionSet
• From API 21
• Slide
• Explode
• ChangeClipBounds
• ChangeImageTransform
• ChangeTransform
val transitionSet = TransitionSet()
transitionSet.ordering = TransitionSet.ORDERING_SEQUENTIAL
transitionSet.addTransition(Slide(Gravity.RIGHT))
transitionSet.addTransition(ChangeBounds())
TransitionManager.beginDelayedTransition(
constraintLayout, transitionSet)
val visibility = if (fieldsVisible) View.VISIBLE else View.GONE
txtNome.visibility = visibility
edtNome.visibility = visibility
txtIdade.visibility = visibility
edtIdade.visibility = visibility
<transitionSet xmlns:android=“…”
android:transitionOrdering=“sequential">
<slide android:slideEdge="right"/>
<changeBounds />
</transitionSet>
val transition = TransitionInflater.from(this)
.inflateTransition(R.transition.transition_form)
TransitionManager.beginDelayedTransition(
constraintLayout, transition)
animation.addListener(object : Transition.TransitionListener {
override fun onTransitionEnd(transition: Transition?) {
}
override fun onTransitionResume(transition: Transition?) {
}
override fun onTransitionPause(transition: Transition?) {
}
override fun onTransitionCancel(transition: Transition?) {
}
override fun onTransitionStart(transition: Transition?) {
}
})
Custom Transition
class CircleViewProgressTransition(context: Context, attrs: AttributeSet)
: Transition(context, attrs) {
override fun captureStartValues(transitionValues: TransitionValues) {
captureValues(transitionValues)
}
override fun captureEndValues(transitionValues: TransitionValues) {
captureValues(transitionValues)
}
private fun captureValues(transitionValues: TransitionValues) {
if (transitionValues.view is CircleView) {
val circleView = transitionValues.view as CircleView
transitionValues.values.put(PROPNAME_ANGLE, circleView.getAngle())
}
}
...
companion object {
private val PROPNAME_ANGLE = "myapp.ui.view:CircleView:angle"
}
}
Custom Transition
override fun createAnimator(sceneRoot: ViewGroup, startValues: TransitionValues?,
endValues: TransitionValues?): Animator? {
if (startValues != null && endValues != null && endValues.view is CircleView) {
val circleView = endValues.view as CircleView
val startAngle = startValues.values[PROPNAME_ANGLE] as Float
val endAngle = endValues.values[PROPNAME_ANGLE] as Float
if (startAngle != endAngle) {
circleView.setAngle(startAngle)
val animCircleProgress = ObjectAnimator.ofFloat(
circleView, CircleView.ANGLE, endAngle)
animCircleProgress.setInterpolator(AccelerateDecelerateInterpolator())
animCircleProgress.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
circleView.setAngle(endAngle)
}
})
return animCircleProgress
}
}
return null
}
android.support.transition
• O Google fornece uma biblioteca de suporte para
v14+
• Mas apenas um subconjunto está disponível:
• AutoTransition, ChangeBounds, Fade,
TransitionSet
• Scene e TransitionManager
• TransitionInflater NÃO está disponível.
4ª geração
Activity & Fragment
Transitions
Activity & Fragment Transitions
• Disponível a partir do Android 5 (API 21)
• Maneira melhor de coreografar animações entre
activities/fragments
• Content transitions permitem especificar como as
views saem e entram na tela
• Shared element transition são elementos presentes
em ambas as telas onde podemos fazer uma
transição mais suave
Window Transitions
<style name="MyCustomTheme" parent="AppTheme">
<item name="android:windowExitTransition">@transition/exit</item>
<item name="android:windowEnterTransition">@transition/enter</item>
<item name="android:windowReenterTransition">@transition/reenter</item>
<item name="android:windowReturnTransition">@transition/return</item>
...
</style>
window.exitTransition = transition
window.enterTransition = transition
window.reenterTransition = transition
window.returnTransition = transition
<explode xmlns:android=“…”/>
res/transition-v21/list_exit.xml
<style name="ListDiscosTheme" parent="AppTheme">
<item name="android:windowExitTransition">@transition/list_exit</item>
<item name="android:windowReenterTransition">@transition/list_exit</item>
</style>
res/values-v21/styles.xml
val it = Intent(this, DetailAlbumActivity::class.java)
it.putExtra(DetailAlbumActivity.EXTRA_DISCO, Parcels.wrap(disco))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val options = ActivityOptions.makeSceneTransitionAnimation(this).toBundle()
startActivity(it, options)
} else {
startActivity(it)
}
val it = Intent(this, DetailAlbumActivity::class.java)
it.putExtra(DetailAlbumActivity.EXTRA_DISCO, Parcels.wrap(disco))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val options = ActivityOptions.makeSceneTransitionAnimation(this).toBundle()
startActivity(it, options)
} else {
startActivity(it)
}
override fun onCreate(savedInstanceState: Bundle?) {
setupWindowAnimations()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_list_albums)
// ...
}
private fun setupWindowAnimations() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val transition = Explode()
window.exitTransition = transition
window.reenterTransition = transition
}
}
Shared Element Transition
<style name="ListDiscosTheme" parent="AppTheme">
<item name=“android:windowSharedElementExitTransition">
@transition/shd_exit
</item>
<item name=“android:windowSharedElementEnterTransition">
@transition/shd_enter
</item>
<item name=“android:windowSharedElementReenterTransition">
@transition/shd_reenter
</item>
<item name=“android:windowSharedElementReturnTransition">
@transition/shd_return
</item>
...
</style>
window.sharedElementExitTransition = transition
window.sharedElementEnterTransition = transition
window.sharedElementReenterTransition = transition
window.sharedElementReturnTransition = transition
Shared Element Transition
val it = Intent(this, DetailAlbumActivity::class.java)
it.putExtra(DetailAlbumActivity.EXTRA_DISCO, Parcels.wrap(disco))
val options = ActivityOptions.makeSceneTransitionAnimation(
this,
Pair(view.findViewById(R.id.imgCapa), "capa"),
Pair(view.findViewById(R.id.txtTitulo), "titulo"),
Pair(view.findViewById(R.id.txtAno), "ano")
).toBundle()
startActivity(it, options)
<style name="ListDiscosTheme" parent="AppTheme">
...
<item name="android:windowContentTransitions">true</item>
</style>
ViewCompat.setTransitionName(imgCapa, "capa")
ViewCompat.setTransitionName(txtTitulo, "titulo")
ViewCompat.setTransitionName(txtAno, "ano")
res/values-v21/styles.xml
ListAlbumsActivity
DetailAlbumActivity
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
Shared Element Transition em Fragments
ChangeBounds changeBoundsTransition = TransitionInflater.from(this)
.inflateTransition(R.transition.change_bounds);
fragmentB.setSharedElementEnterTransition(changeBoundsTransition);
getFragmentManager().beginTransaction()
.replace(R.id.content, fragmentB)
.addSharedElement(blueView, getString(R.string.blue_name))
.commit();
Reveal animation
val transition = AutoTransition()
transition.duration = resources.getInteger(
android.R.integer.config_mediumAnimTime).toLong()
transition.pathMotion = GravityArcMotion()
val constraintSet = ConstraintSet()
constraintSet.clone(constraintlayout)
TransitionManager.beginDelayedTransition(constraintlayout, transition)
constraintSet.clear(R.id.fabAdd, ConstraintSet.BOTTOM)
constraintSet.clear(R.id.fabAdd, ConstraintSet.RIGHT)
constraintSet.connect(R.id.fabAdd, ConstraintSet.TOP,
R.id.cardViewCity, ConstraintSet.TOP)
constraintSet.connect(R.id.fabAdd, ConstraintSet.LEFT,
R.id.cardViewCity, ConstraintSet.LEFT)
constraintSet.connect(R.id.fabAdd, ConstraintSet.BOTTOM,
R.id.cardViewCity, ConstraintSet.BOTTOM)
constraintSet.connect(R.id.fabAdd, ConstraintSet.RIGHT,
R.id.cardViewCity, ConstraintSet.RIGHT)
constraintSet.applyTo(constraintlayout)
https://github.com/nickbutcher/plaid/blob/master/app/src/main/java/io/plaidapp/ui/transitions/GravityArcMotion.java
val cx = (cardViewCity.left + cardViewCity.right) / 2
val cy = (cardViewCity.top + cardViewCity.bottom) / 2
val anim = ViewAnimationUtils.createCircularReveal(
cardViewCity, cx, cy, fabAdd.width.toFloat(), cardViewCity.width.toFloat())
cardViewCity.visibility = View.VISIBLE
anim.start()
val cx = (cardViewCity.left + cardViewCity.right) / 2
val cy = (cardViewCity.top + cardViewCity.bottom) / 2
val anim = ViewAnimationUtils.createCircularReveal(
cardViewCity, cx, cy, cardViewCity.width.toFloat(), fabAdd.width.toFloat())
anim.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
cardViewCity.visibility = View.INVISIBLE
}
})
}
anim.start()
<style name="RevealActivityMain" parent="AppTheme">
<item name="android:windowContentTransitions">true</item>
</style>
val options = ActivityOptionsCompat
.makeSceneTransitionAnimation(this, Pair(fabAdd, "circular"))
.toBundle()
startActivity(Intent(this, RevealDetailActivity::class.java), options)
<autoTransition xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="@android:integer/config_longAnimTime">
<arcMotion
android:maximumAngle="90"
android:minimumHorizontalAngle="15"
android:minimumVerticalAngle="0" />
</autoTransition>
<style name="RevealActivityDetail" parent="AppTheme">
<item name="android:windowContentTransitions">true</item>
<item name=“android:windowSharedElementEnterTransition">
@transition/transition_activity_reveal
</item>
</style>
ViewCompat.setTransitionName(viewPlaceHolder, "circular")
if (isLollipopOrLater() && savedInstanceState == null) {
viewTop.visibility = View.INVISIBLE
window.sharedElementEnterTransition.addListener(
object: TransitionListenerAdapter() {
override fun onTransitionEnd(transition: Transition?) {
super.onTransitionEnd(transition)
circularRevealActivity()
}
})
}
Animated Vector
Drawable
AnimatedVectorDrawable
• Um vector drawable é composto por uma série
padronizada de comandos chamada de path.
• É possível criar um group desses comandos.
• Um animated vector drawable nos permite animar
parte de um vector drawable.
companion object {
init {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
}
}
android {
...
defaultConfig {
...
vectorDrawables.useSupportLibrary true
}
Path (Comandos)
• M x,y

começa um novo subpath movendo para x,y
• L x,y

desenha uma linha para x,y
• C x1,y1 x2,y2 x,y

desenha uma curva de Bezier cúbica para x,y usando os
pontos de controle x1,y1 e x2,y2
• Z

Fecha um path desenhando uma linha reta de volta ao
ponto de origem do subpath atual
L3,10 L6,8
L6,4
M3,2 Z
M6,4
L6,8
L9,6
L6,4Z
M3,2
L3,10
L5,10
L5,2
Z M7,2
L7,10
L9,10
L9,2
Z
<string name="path_play_1">M 3,2 L 3,10 L 6,8 L 6,4 Z</string>
<string name="path_play_2">M 6,4 L 6,8 L 9,6 L 6,4 Z</string>
res/values/strings.xml
<string name="path_pause_1">M 3,2 L 3,10 L 5,10 L 5,2 Z</string>
<string name="path_pause_2">M 7,2 L 7,10 L 9,10 L 9,2 Z</string>
res/values/strings.xml
drawable
values
drawable-v21
values-v21
ic_vector_play.xml
ic_vector_pause.xml
ic_avd_pause_play.xml
ic_avd_play_pause.xml
refs.xml
refs.xml
Vector Drawables
Animated

Vector Drawables
Referência de acordo
com a versão
<vector xmlns:android="..."
android:width="48dp"
android:height="48dp"
android:viewportHeight="12"
android:viewportWidth="12">
<group
android:name="triangle"
android:pivotX="6"
android:pivotY="6">
<path
android:name="triangle_1"
android:fillColor="#FFFFFF"
android:pathData="@string/path_play_1" />
<path
android:name="triangle_2"
android:fillColor="#FFFFFF"
android:pathData="@string/path_play_2" />
</group>
</vector>
ic_vector_play.xml
<vector xmlns:android="..."
android:width="48dp"
android:height="48dp"
android:viewportHeight="12"
android:viewportWidth="12">
<path
android:name="bar_1"
android:fillColor="#FFFFFF"
android:pathData="@string/path_pause_1" />
<path
android:name="bar_2"
android:fillColor="#FFFFFF"
android:pathData="@string/path_pause_2" />
</vector>
ic_vector_pause.xml
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:drawable="@drawable/ic_vector_play">
<target android:name="triangle">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="180"
android:valueType="floatType" />
</aapt:attr>
</target>
<target android:name="triangle_1">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:propertyName="pathData"
android:valueFrom="@string/path_play_1"
android:valueTo="@string/path_pause_1"
android:valueType="pathType" />
</aapt:attr>
</target>
<target android:name="triangle_2">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:propertyName="pathData"
android:valueFrom="@string/path_play_2"
android:valueTo="@string/path_pause_2"
android:valueType="pathType" />
</aapt:attr>
</target>
</animated-vector>
ic_avd_play_pause.xml
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:drawable="@drawable/ic_vector_pause">
<target android:name="bar_1">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:propertyName="pathData"
android:valueFrom="@string/path_pause_1"
android:valueTo="@string/path_play_1"
android:valueType="pathType" />
</aapt:attr>
</target>
<target android:name="bar_2">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="300"
android:propertyName="pathData"
android:valueFrom="@string/path_pause_2"
android:valueTo="@string/path_play_2"
android:valueType="pathType" />
</aapt:attr>
</target>
</animated-vector>
ic_avd_pause_play.xml
<resources>
<item name="ic_play" type="drawable">@drawable/ic_vector_play</item>
<item name="ic_pause" type="drawable">@drawable/ic_vector_pause</item>
</resources>
<resources>
<item name="ic_play" type="drawable">@drawable/ic_avd_play_pause</item>
<item name="ic_pause" type=“drawable">@drawable/ic_avd_pause_play</item>
</resources>
<ImageView
...
app:srcCompat="@drawable/ic_play" />
values
values-v21
refs.xml
refs.xml
fun getIconDrawable(): Drawable? {
val drawableId: Int
if (isPlaying) {
drawableId = R.drawable.ic_play
} else {
drawableId = R.drawable.ic_pause
}
return ResourcesCompat.getDrawable(resources, drawableId, theme)
}
private fun togglePlayPause() {
isPlaying = !isPlaying
imageAnimatedVector.setImageDrawable(getIconDrawable())
animateButton(imageAnimatedVector.drawable)
}
private fun animateButton(icon: Drawable?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
icon is AnimatedVectorDrawable) {
icon.start()
}
}
https://romannurik.github.io/AndroidIconAnimator/
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="56dp"
android:height="56dp"
android:tint="?attr/colorControlNormal"
android:viewportHeight="56"
android:viewportWidth="56">
<path
android:pathData="@string/heart_stroke_left"
android:strokeColor="@android:color/white"
android:strokeWidth="2"/>
<path
android:pathData="@string/heart_stroke_right"
android:strokeColor="@android:color/white"
android:strokeWidth="2"/>
</vector>
res/drawable/ic_vector_heart_empty.xml
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="56dp"
android:height="56dp"
android:tint="?attr/colorControlNormal"
android:viewportHeight="56"
android:viewportWidth="56">
<!-- mesmos paths do fill -->
<group android:name="filled">
<clip-path
android:name="clip"
android:pathData="@string/heart_clip_shown"/>
<path
android:fillColor="@android:color/white"
android:pathData="@string/heart_full_path"/>
</group>
</vector>
res/drawable/ic_vector_heart_full.xml
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:drawable="@drawable/ic_vector_heart_full">
<target android:name="clip">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="@android:integer/config_mediumAnimTime"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="@string/heart_clip_shown"
android:valueTo="@string/heart_clip_hidden"
android:valueType="pathType"/>
</aapt:attr>
</target>
</animated-vector>
res/drawable-v21/ic_avd_heart_full_empty.xml
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:drawable="@drawable/ic_vector_heart_full">
<target android:name="clip">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="@android:integer/config_mediumAnimTime"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="@string/heart_clip_hidden"
android:valueTo="@string/heart_clip_shown"
android:valueType="pathType"/>
</aapt:attr>
</target>
</animated-vector>
res/drawable-v21/ic_avd_heart_empty_full.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/liked"
android:drawable="@drawable/ic_vector_heart_full"
android:state_checked="true"/>
<item
android:id="@+id/not_liked"
android:drawable="@drawable/ic_vector_heart_empty"/>
</selector>
drawable/selector_heart.xml
<animated-selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/liked"
android:drawable="@drawable/ic_vector_heart_full"
android:state_checked="true" />
<item
android:id="@+id/not_liked"
android:drawable="@drawable/ic_vector_heart_empty" />
<transition
android:drawable="@drawable/ic_avd_heart_empty_full"
android:fromId="@id/not_liked"
android:toId="@id/liked" />
<transition
android:drawable="@drawable/ic_avd_heart_full_empty"
android:fromId="@id/liked"
android:toId="@id/not_liked" />
</animated-selector>
drawable-v21/selector_heart.xml
Physics-based
animation
https://developer.android.com/guide/topics/graphics/spring-animation.html
https://gist.github.com/nickbutcher/7fdce476aaa589680cdd626d78e3149d
E aquela animação, que
gira, pula, solta fogos…🤔
https://github.com/airbnb/lottie-android
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lottie_fileName="assetSubDir/spring.json"
app:lottie_loop="true"
app:lottie_autoPlay="true" />
LottieAnimationView animationView = (LottieAnimationView)
findViewById(R.id.animation_view);
animationView.setAnimation("assetSubDir/spring.json");
animationView.loop(true);
animationView.playAnimation();
dependencies {
compile 'com.airbnb.android:lottie:2.0.0-beta4'
}
Algumas libs…
• https://github.com/andkulikov/Transitions-Everywhere
• https://github.com/willowtreeapps/spruce-android
• https://github.com/glomadrian/Grav
• https://github.com/daimajia/AndroidViewAnimations
• https://github.com/2359media/
EasyAndroidAnimations
• http://facebook.github.io/rebound/
Referências
• Material Design para Desenvolvedores Android

https://br.udacity.com/course/material-design-for-android-developers--ud862/
• Andre Mion Animations

https://stories.uplabs.com/music-player-3a85864d6df7

https://blog.prototypr.io/applying-meaningful-motion-on-android-
a271a873bd78
• Plaid (Nick Butcher)

https://github.com/nickbutcher/plaid
• Animatable (Nick Butcher)

https://goo.gl/99Y9qD
Referências
• Android transitions with examples

https://github.com/lgvalle/Material-Animations
• An Introduction to Icon Animation Techniques

http://www.androiddesignpatterns.com/2016/11/introduction-to-icon-
animation-techniques.html
• Animate all the things. Transitions in Android

https://medium.com/@andkulikov/animate-all-the-things-transitions-in-
android-914af5477d50
• Animate me, If you don't do it for me do it for Chet :)

https://pt.slideshare.net/Android2EE/animate-me-if-you-dont-do-it-for-me-do-
it-for-chet
Dúvidas?
@nglauber
+NelsonGlauber
www.nglauber.com.br

More Related Content

Similar to The world of Android Animations

Basic Android Animation
Basic Android Animation Basic Android Animation
Basic Android Animation
Shilu Shrestha
 
Day seven
Day sevenDay seven
Day seven
Vivek Bhusal
 
Android view animation in android-chapter18
Android view animation in android-chapter18Android view animation in android-chapter18
Android view animation in android-chapter18
Dr. Ramkumar Lakshminarayanan
 
How to Create Animation Using the AnimatedAlign Widget.pptx
How to Create Animation Using the AnimatedAlign Widget.pptxHow to Create Animation Using the AnimatedAlign Widget.pptx
How to Create Animation Using the AnimatedAlign Widget.pptx
Flutter Agency
 
Макс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложенияхМакс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложениях
CocoaHeads
 
Android Oreo
Android OreoAndroid Oreo
Android Oreo
Siddharth Yadav
 
Enhancing UI/UX using Java animations
Enhancing UI/UX using Java animationsEnhancing UI/UX using Java animations
Enhancing UI/UX using Java animations
Naman Dwivedi
 
Animation in android
Animation in androidAnimation in android
Animation in android
Jatin_123
 
Android Wear Essentials
Android Wear EssentialsAndroid Wear Essentials
Android Wear Essentials
Nilhcem
 
How to implement react native animations using animated api
How to implement react native animations using animated apiHow to implement react native animations using animated api
How to implement react native animations using animated api
Katy Slemon
 
Seven Peaks Speaks - Android Jetpack Compose Animation
Seven Peaks Speaks - Android Jetpack Compose AnimationSeven Peaks Speaks - Android Jetpack Compose Animation
Seven Peaks Speaks - Android Jetpack Compose Animation
Seven Peaks Speaks
 
Angular animate
Angular animateAngular animate
Angular animate
Yating Chatiron
 
Android App Development - 12 animations
Android App Development - 12 animationsAndroid App Development - 12 animations
Android App Development - 12 animations
Diego Grancini
 
MCE^3 - Marin Todorov - Building Swift Libraries for iOS
MCE^3 - Marin Todorov -  Building Swift Libraries for iOSMCE^3 - Marin Todorov -  Building Swift Libraries for iOS
MCE^3 - Marin Todorov - Building Swift Libraries for iOS
PROIDEA
 
Animate me, If you don't do it for me do it for Chet :)
Animate me, If you don't do it for me do it for Chet :)Animate me, If you don't do it for me do it for Chet :)
Animate me, If you don't do it for me do it for Chet :)
Mathias Seguy
 
YUI for Mobile - HTML5DevConf 11
YUI for Mobile - HTML5DevConf 11YUI for Mobile - HTML5DevConf 11
YUI for Mobile - HTML5DevConf 11
Gonzalo Cordero
 
Beauty Treatment for your Android Application
Beauty Treatment for your Android ApplicationBeauty Treatment for your Android Application
Beauty Treatment for your Android Application
Codemotion
 
Android 2D Drawing and Animation Framework
Android 2D Drawing and Animation FrameworkAndroid 2D Drawing and Animation Framework
Android 2D Drawing and Animation Framework
Jussi Pohjolainen
 
[Android] Android Animation
[Android] Android Animation[Android] Android Animation
[Android] Android Animation
Nikmesoft Ltd
 
Expand/Collapse animation on Android
Expand/Collapse animation on AndroidExpand/Collapse animation on Android
Expand/Collapse animation on Android
Pavlo Dudka
 

Similar to The world of Android Animations (20)

Basic Android Animation
Basic Android Animation Basic Android Animation
Basic Android Animation
 
Day seven
Day sevenDay seven
Day seven
 
Android view animation in android-chapter18
Android view animation in android-chapter18Android view animation in android-chapter18
Android view animation in android-chapter18
 
How to Create Animation Using the AnimatedAlign Widget.pptx
How to Create Animation Using the AnimatedAlign Widget.pptxHow to Create Animation Using the AnimatedAlign Widget.pptx
How to Create Animation Using the AnimatedAlign Widget.pptx
 
Макс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложенияхМакс Грибов — Использование SpriteKit в неигровых приложениях
Макс Грибов — Использование SpriteKit в неигровых приложениях
 
Android Oreo
Android OreoAndroid Oreo
Android Oreo
 
Enhancing UI/UX using Java animations
Enhancing UI/UX using Java animationsEnhancing UI/UX using Java animations
Enhancing UI/UX using Java animations
 
Animation in android
Animation in androidAnimation in android
Animation in android
 
Android Wear Essentials
Android Wear EssentialsAndroid Wear Essentials
Android Wear Essentials
 
How to implement react native animations using animated api
How to implement react native animations using animated apiHow to implement react native animations using animated api
How to implement react native animations using animated api
 
Seven Peaks Speaks - Android Jetpack Compose Animation
Seven Peaks Speaks - Android Jetpack Compose AnimationSeven Peaks Speaks - Android Jetpack Compose Animation
Seven Peaks Speaks - Android Jetpack Compose Animation
 
Angular animate
Angular animateAngular animate
Angular animate
 
Android App Development - 12 animations
Android App Development - 12 animationsAndroid App Development - 12 animations
Android App Development - 12 animations
 
MCE^3 - Marin Todorov - Building Swift Libraries for iOS
MCE^3 - Marin Todorov -  Building Swift Libraries for iOSMCE^3 - Marin Todorov -  Building Swift Libraries for iOS
MCE^3 - Marin Todorov - Building Swift Libraries for iOS
 
Animate me, If you don't do it for me do it for Chet :)
Animate me, If you don't do it for me do it for Chet :)Animate me, If you don't do it for me do it for Chet :)
Animate me, If you don't do it for me do it for Chet :)
 
YUI for Mobile - HTML5DevConf 11
YUI for Mobile - HTML5DevConf 11YUI for Mobile - HTML5DevConf 11
YUI for Mobile - HTML5DevConf 11
 
Beauty Treatment for your Android Application
Beauty Treatment for your Android ApplicationBeauty Treatment for your Android Application
Beauty Treatment for your Android Application
 
Android 2D Drawing and Animation Framework
Android 2D Drawing and Animation FrameworkAndroid 2D Drawing and Animation Framework
Android 2D Drawing and Animation Framework
 
[Android] Android Animation
[Android] Android Animation[Android] Android Animation
[Android] Android Animation
 
Expand/Collapse animation on Android
Expand/Collapse animation on AndroidExpand/Collapse animation on Android
Expand/Collapse animation on Android
 

More from Nelson Glauber Leal

Seu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformSeu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose Multiplatform
Nelson Glauber Leal
 
Desenvolvimento Moderno de Aplicações Android 2023
Desenvolvimento Moderno de Aplicações Android 2023Desenvolvimento Moderno de Aplicações Android 2023
Desenvolvimento Moderno de Aplicações Android 2023
Nelson Glauber Leal
 
Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023
Nelson Glauber Leal
 
Novidades das Bibliotecas Jetpack do Android (2021)
Novidades das Bibliotecas Jetpack do Android (2021)Novidades das Bibliotecas Jetpack do Android (2021)
Novidades das Bibliotecas Jetpack do Android (2021)
Nelson Glauber Leal
 
Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021
Nelson Glauber Leal
 
Jetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on AndroidJetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on Android
Nelson Glauber Leal
 
Jetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no AndroidJetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no Android
Nelson Glauber Leal
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
Nelson Glauber Leal
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
Nelson Glauber Leal
 
O que é preciso para ser um desenvolvedor Android
O que é preciso para ser um desenvolvedor AndroidO que é preciso para ser um desenvolvedor Android
O que é preciso para ser um desenvolvedor Android
Nelson Glauber Leal
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
Nelson Glauber Leal
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
Nelson Glauber Leal
 
Aplicações Assíncronas no Android com Coroutines e Jetpack
Aplicações Assíncronas no Android com Coroutines e JetpackAplicações Assíncronas no Android com Coroutines e Jetpack
Aplicações Assíncronas no Android com Coroutines e Jetpack
Nelson Glauber Leal
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
Nelson Glauber Leal
 
Aplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackAplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & Jetpack
Nelson Glauber Leal
 
Introdução ao Desenvolvimento Android com Kotlin
Introdução ao Desenvolvimento Android com KotlinIntrodução ao Desenvolvimento Android com Kotlin
Introdução ao Desenvolvimento Android com Kotlin
Nelson Glauber Leal
 
Persisting Data on SQLite using Room
Persisting Data on SQLite using RoomPersisting Data on SQLite using Room
Persisting Data on SQLite using Room
Nelson Glauber Leal
 
Arquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com JetpackArquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com Jetpack
Nelson Glauber Leal
 
Desenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de Aplicativos AndroidDesenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de Aplicativos Android
Nelson Glauber Leal
 
Desenvolvimento Moderno de aplicativos Android
Desenvolvimento Moderno de aplicativos AndroidDesenvolvimento Moderno de aplicativos Android
Desenvolvimento Moderno de aplicativos Android
Nelson Glauber Leal
 

More from Nelson Glauber Leal (20)

Seu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformSeu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose Multiplatform
 
Desenvolvimento Moderno de Aplicações Android 2023
Desenvolvimento Moderno de Aplicações Android 2023Desenvolvimento Moderno de Aplicações Android 2023
Desenvolvimento Moderno de Aplicações Android 2023
 
Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023
 
Novidades das Bibliotecas Jetpack do Android (2021)
Novidades das Bibliotecas Jetpack do Android (2021)Novidades das Bibliotecas Jetpack do Android (2021)
Novidades das Bibliotecas Jetpack do Android (2021)
 
Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021
 
Jetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on AndroidJetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on Android
 
Jetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no AndroidJetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no Android
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
 
O que é preciso para ser um desenvolvedor Android
O que é preciso para ser um desenvolvedor AndroidO que é preciso para ser um desenvolvedor Android
O que é preciso para ser um desenvolvedor Android
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
Aplicações Assíncronas no Android com Coroutines e Jetpack
Aplicações Assíncronas no Android com Coroutines e JetpackAplicações Assíncronas no Android com Coroutines e Jetpack
Aplicações Assíncronas no Android com Coroutines e Jetpack
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
 
Aplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackAplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & Jetpack
 
Introdução ao Desenvolvimento Android com Kotlin
Introdução ao Desenvolvimento Android com KotlinIntrodução ao Desenvolvimento Android com Kotlin
Introdução ao Desenvolvimento Android com Kotlin
 
Persisting Data on SQLite using Room
Persisting Data on SQLite using RoomPersisting Data on SQLite using Room
Persisting Data on SQLite using Room
 
Arquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com JetpackArquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com Jetpack
 
Desenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de Aplicativos AndroidDesenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de Aplicativos Android
 
Desenvolvimento Moderno de aplicativos Android
Desenvolvimento Moderno de aplicativos AndroidDesenvolvimento Moderno de aplicativos Android
Desenvolvimento Moderno de aplicativos Android
 

The world of Android Animations