O sistema de animação de propriedades é um framework robusto que permite para animar quase tudo. Você pode definir uma animação para alterar qualquer propriedade de objeto ao longo do tempo, independentemente de ser desenhado na tela ou não. Uma animação de propriedade muda o (um campo em um objeto) valor durante um período especificado. Para animar algo, você especifica o propriedade de objeto que você quer animar, como a posição de um objeto na tela, por quanto tempo e com quais valores você quer fazer a animação.
O sistema de animação de propriedades permite definir as seguintes características de uma animação:
- Duração: é possível especificar a duração de uma animação. O padrão é 300 ms.
- Interpolação de tempo: você pode especificar como os valores para a propriedade são calculados como uma função do tempo decorrido atual da animação.
- Repetir contagem e comportamento: é possível especificar se uma animação deve ou não ser repetida quando atinge o final de uma duração e quantas vezes a animação é repetida. Você também pode especifique se você quer que a animação seja reproduzida no sentido inverso. Configuração para inverter a reprodução a animação avança e retrocede repetidamente até que o número de repetições seja atingido.
- Conjuntos de animadores: você pode agrupar animações em conjuntos lógicos que são reproduzidos juntos ou sequencialmente ou após atrasos especificados.
- Atraso da atualização do frame: é possível especificar com que frequência os frames da animação serão atualizados. A por padrão está definido para atualizar a cada 10 ms, mas a velocidade com que seu aplicativo pode atualizar frames é depende de quão ocupado o sistema está em geral e quão rápido ele consegue atender ao timer subjacente.
Para ver um exemplo completo de animação de propriedade, consulte a
Classe ChangeColor
na classe CustomTransition
no GitHub.
Como a animação de propriedade funciona
Primeiro, vamos ver como uma animação funciona com um exemplo simples. A Figura 1 ilustra uma
objeto hipotético animado com a propriedade x
, que representa a
localização horizontal em uma tela. A duração da animação é definida como 40 ms e a distância
é de 40 pixels. A cada 10 ms, que é a taxa de atualização de frames padrão, o objeto se move
horizontalmente por 10 pixels. Ao final de 40 ms, a animação para, e o objeto termina em
na posição horizontal 40. Este é um exemplo de animação com interpolação linear, o que significa que o
ou objeto se move a uma velocidade constante.
![](https://developer.android.com/static/images/animation/animation-linear.png?authuser=9&hl=pt-br)
Figura 1. Exemplo de uma animação linear.
Também é possível especificar que animações tenham uma interpolação não linear. A Figura 2 ilustra uma objeto hipotético que acelera no início da animação e desacelera no final da animação. O objeto ainda percorre 40 pixels em 40 ms, mas não de forma linear. Na a animação vai acelerar até a metade do caminho e desacelerar do ponto até o ponto médio até o final da animação. Conforme exibido na Figura 2, a distância percorrida no início e no final da animação é menor do que no meio.
![](https://developer.android.com/static/images/animation/animation-nonlinear.png?authuser=9&hl=pt-br)
Figura 2. Exemplo de uma animação não linear.
Vamos conferir em detalhes como os componentes importantes do sistema de animação de propriedades calcularia animações como as ilustradas acima. A Figura 3 ilustra como as classes principais trabalham umas com as outras.
![](https://developer.android.com/static/images/animation/valueanimator.png?authuser=9&hl=pt-br)
Figura 3. Como as animações são calculadas.
O objeto ValueAnimator
monitora o tempo da animação.
por exemplo, há quanto tempo a animação foi executada e o valor atual da propriedade
e animação.
O ValueAnimator
encapsula um TimeInterpolator
, que define a interpolação da animação, e um TypeEvaluator
, que define como calcular valores para a propriedade que está sendo
animada. Por exemplo, na Figura 2, o TimeInterpolator
usado seria
AccelerateDecelerateInterpolator
e TypeEvaluator
seria IntEvaluator
.
Para iniciar uma animação, crie uma ValueAnimator
e atribua a ela o
valores inicial e final da propriedade que você quer animar, juntamente com a duração dos
a animação. Quando você chama start()
, a animação
começa. Durante toda a animação, o ValueAnimator
calcula uma fração decorrida.
entre 0 e 1, com base na duração da animação e em quanto tempo já passou. A
fração decorrida representa a porcentagem de tempo que a animação terminou, 0 significa 0%
e 1 significa 100%. Por exemplo, na Figura 1, a fração decorrida em t = 10 ms seria 0,25
porque a duração total é t = 40 ms.
Quando o ValueAnimator
terminar de calcular uma fração decorrida, ela
chama o TimeInterpolator
definido no momento para calcular uma
fração interpolada. Uma fração interpolada mapeia a fração decorrida para uma nova
que leva em conta a interpolação de tempo definida. Por exemplo, na Figura 2,
como a animação acelera lentamente, a fração interpolada, cerca de 0,15, é menor que a
fração decorrida, 0,25, em t = 10 ms. Na figura 1, a fração interpolada é sempre a mesma que
a fração decorrida.
Quando a fração interpolada é calculada, ValueAnimator
chama
o TypeEvaluator
apropriado para calcular o valor do
que você está animando, com base na fração interpolada, o valor inicial e a
o valor final da animação. Por exemplo, na figura 2, a fração interpolada era 0,15 em t =
10 ms, portanto, o valor da propriedade nesse momento seria 0,15 × (40 - 0) ou 6.
Diferenças entre a animação de propriedade e a animação de visualização
O sistema de animação de visualizações permite animar apenas View
.
portanto, se quiser animar objetos que não são View
, será necessário implementar
seu próprio código para fazer isso. O sistema de animação de visualizações também é limitado, porque
expõe alguns aspectos de um objeto View
para animar, como o dimensionamento e
rotação de uma visualização, mas não a cor de fundo, por exemplo.
Outra desvantagem do sistema de animação de visualizações é que ele só modifica onde A visualização foi desenhada, e não a visualização em si. Por exemplo, se você animou um botão para se mover na tela, o botão é desenhado corretamente, mas o local real em que você pode clicar não muda, então você precisa implementar sua própria lógica para lidar com isso.
Com o sistema de animação de propriedades, essas restrições são completamente removidas, e você pode animar qualquer propriedade de qualquer objeto (visualizações e não visualizações), e o objeto em si é realmente modificado. O sistema de animação de propriedades também é mais robusto na forma como realiza animações. Em em alto nível, você atribui animadores às propriedades que deseja animar, como cor, posição ou tamanho e pode definir aspectos da animação, como interpolação e e a sincronização de vários animadores.
No entanto, o sistema de animação de visualizações leva menos tempo para ser configurado e requer menos código. Se a animação de visualização realizar tudo o que você precisa ou se o código existente já funcionar da maneira desejada, não será necessário usar o sistema de animação de propriedades. Também pode faz sentido usar ambos os sistemas de animação para diferentes situações se surgir o caso de uso.
Visão geral da API
Veja a maioria das APIs do sistema de animação de propriedades em android.animation
. Como o sistema de animação de visualizações
define muitos interpoladores em android.view.animation
, é possível usar
esses interpoladores no sistema de animação de propriedades. As tabelas a seguir descrevem os principais
componentes do sistema de animação de propriedades.
A classe Animator
fornece a estrutura básica para criar
animações. Normalmente, você não usa essa classe diretamente, porque ela fornece apenas o mínimo
funcionalidade que precisa ser estendida para oferecer suporte total à animação de valores. O seguinte
as subclasses estendem Animator
:
Tabela 1. Animadores.
Classe | Descrição |
---|---|
ValueAnimator |
O principal mecanismo de tempo para animação de propriedade que também calcula os valores para o
seja animada. Ele tem todos os recursos principais que calculam animações
valores e contém os detalhes de tempo de cada animação, informações sobre se um
animações repetidas, listeners que recebem eventos de atualização e a capacidade de definir
que devem ser avaliados. Há duas partes na animação de propriedades: o cálculo da animação
e configurando esses valores no objeto e na propriedade que está sendo animado. ValueAnimator não pode processar a segunda peça, então você precisa ouvir
para atualizações de valores calculados pelos métodos ValueAnimator e
modificar os objetos que você quer animar com sua própria lógica. Consulte a seção sobre
Animar com ValueAnimator para mais informações. |
ObjectAnimator |
Uma subclasse de ValueAnimator que permite definir um destino.
objeto e propriedade de objeto a serem animados. Essa classe atualiza a propriedade adequadamente quando
ele calcula um novo valor para a animação. Você quer usar
ObjectAnimator na maioria das vezes,
porque isso torna o processo de animação de valores em objetos de destino muito mais fácil. No entanto,
às vezes você vai querer usar ValueAnimator diretamente porque ObjectAnimator tem mais algumas restrições, como exigir
métodos do acessador estejam presentes no objeto de destino. |
AnimatorSet |
Fornece um mecanismo para agrupar animações para que elas sejam executadas em relação entre si. É possível definir animações para serem exibidas juntas, em sequência ou depois. um atraso especificado. Consulte a seção Coreografar múltiplos animações com conjuntos de animadores para mais informações. |
Os avaliadores dizem ao sistema de animação de propriedades como calcular valores para um determinado
. Eles usam os dados de tempo fornecidos por um Animator
.
, o valor inicial e final da animação e calcular os valores animados da propriedade
com base nesses dados. O sistema de animação de propriedades disponibiliza os seguintes avaliadores:
Tabela 2. Avaliadores.
Classe/interface | Descrição |
---|---|
IntEvaluator |
Avaliador padrão para calcular valores para propriedades int . |
FloatEvaluator |
Avaliador padrão para calcular valores para propriedades float . |
ArgbEvaluator |
Avaliador padrão para calcular valores para propriedades de cor que são representadas como valores hexadecimais. |
TypeEvaluator |
Interface que permite criar o próprio avaliador. Se você estiver animando
do objeto que não seja int , float ou cor,
você precisa implementar a interface TypeEvaluator para especificar
para calcular os valores animados da propriedade do objeto. Também é possível especificar um TypeEvaluator personalizado para int , float e cor.
valores também, se quiser processar esses tipos de forma diferente do comportamento padrão.
Consulte a seção sobre Como usar um TypeEvaluator para mais
informações sobre como escrever um avaliador personalizado. |
Um interpolador de tempo define como valores específicos em uma animação são calculados como uma
função do tempo. Por exemplo, você pode especificar que animações aconteçam linearmente em todo
animação, ou seja, a animação se move de maneira uniforme o tempo todo, ou você pode especificar animações
usar o tempo não linear, por exemplo, acelerando no início e desacelerando no
final da animação. A Tabela 3 descreve os interpoladores contidos em android.view.animation
. Se nenhum dos interpoladores fornecidos for adequado
de acordo com suas necessidades, implemente a interface TimeInterpolator
e crie a sua própria. Consulte Como usar interpoladores para mais informações sobre como programar um
interpolador.
Tabela 3. Interpoladores
Classe/interface | Descrição |
---|---|
AccelerateDecelerateInterpolator |
Interpolador cuja taxa de mudança começa e termina lentamente, mas acelera no meio. |
AccelerateInterpolator |
Interpolador cuja taxa de mudança começa lentamente e depois e acelera. |
AnticipateInterpolator |
Interpolador cuja mudança começa na ordem inversa e depois avança rapidamente. |
AnticipateOvershootInterpolator |
Interpolador cuja mudança começa na ordem inversa, avança rapidamente e ultrapassa o ponto. o valor de destino e, por fim, volta para o valor final. |
BounceInterpolator |
Interpolador cuja mudança oscila no final. |
CycleInterpolator |
Interpolador cuja animação se repete por um número especificado de ciclos. |
DecelerateInterpolator |
Interpolador cuja taxa de mudança começa rapidamente e depois desacelera. |
LinearInterpolator |
Interpolador cuja taxa de mudança é constante. |
OvershootInterpolator |
Interpolador cuja mudança avança rapidamente e ultrapassa o último valor. volta. |
TimeInterpolator |
Interface que permite implementar o próprio interpolador. |
Animar com o ValueAnimator
A classe ValueAnimator
permite animar valores de algum tipo para o
duração de uma animação especificando um conjunto de int
, float
ou cor
valores para a animação. Para conseguir um ValueAnimator
, chame um dos
os métodos de fábrica: ofInt()
, ofFloat()
ou ofObject()
. Exemplo:
Kotlin
ValueAnimator.ofFloat(0f, 100f).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f); animation.setDuration(1000); animation.start();
Neste código, o ValueAnimator
começa a calcular os valores do
animação, entre 0 e 100, por uma duração de 1.000 ms, quando o método start()
é executado.
Também é possível especificar um tipo personalizado para animação fazendo o seguinte:
Kotlin
ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); animation.setDuration(1000); animation.start();
Neste código, o ValueAnimator
começa a calcular os valores do
entre startPropertyValue
e endPropertyValue
usando o método
lógica fornecida por MyTypeEvaluator
por 1.000 ms, quando o método start()
é executado.
Você pode usar os valores da animação adicionando um
AnimatorUpdateListener
ao objeto ValueAnimator
, conforme mostrado
seguinte código:
Kotlin
ValueAnimator.ofObject(...).apply { ... addUpdateListener { updatedAnimation -> // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. textView.translationX = updatedAnimation.animatedValue as Float } ... }
Java
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } });
No onAnimationUpdate()
você pode acessar o valor de animação atualizado e usá-lo em uma propriedade do
uma das suas visualizações. Para mais informações sobre listeners, consulte a seção sobre
Listeners de animação.
Animar com o ObjectAnimator
O ObjectAnimator
é uma subclasse do ValueAnimator
(discutido na seção anterior) e combina o tempo
Compute Engine e valor de ValueAnimator
, com a capacidade de
animar uma propriedade nomeada de um objeto de destino. Isso torna a animação de qualquer objeto muito mais fácil, pois você
não precisam mais implementar o ValueAnimator.AnimatorUpdateListener
,
porque a propriedade animada
é atualizada automaticamente.
A instanciação de um ObjectAnimator
é semelhante a uma ValueAnimator
, mas você também especifica o objeto e o nome da propriedade desse objeto (como
uma String) junto com os valores que serão animados entre:
Kotlin
ObjectAnimator.ofFloat(textView, "translationX", 100f).apply { duration = 1000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f); animation.setDuration(1000); animation.start();
Para que o ObjectAnimator
atualize as propriedades
faça o seguinte:
- A propriedade do objeto que você está animando deve ter uma função setter (em camelCase) na forma de
set<PropertyName>()
: Como oObjectAnimator
atualiza automaticamente a propriedade durante a animação, ela precisa ser capaz de acessar a propriedade com esse método setter. Por exemplo, se o nome da propriedade forfoo
, será preciso têm um métodosetFoo()
. Se esse método setter não existir, você terá três opções:- Adicione o método setter à classe se você tem os direitos para fazer isso.
- Use uma classe de wrapper que você tenha o direito de mudar e faça com que esse wrapper receba o com um método setter válido e o encaminhe para o objeto original.
- Use
ValueAnimator
- Se você especificar apenas um valor para o parâmetro
values...
em um dos métodos de fábricaObjectAnimator
, ele será considerado o valor final do animação. Portanto, a propriedade do objeto que você está animando precisa ter uma função getter. usada para obter o valor inicial da animação. A função getter deve estar no deget<PropertyName>()
. Por exemplo, se o nome da propriedade forfoo
, você precisa ter um métodogetFoo()
. - Os métodos getter (se necessário) e setter da propriedade que você está animando devem
operam no mesmo tipo que os valores inicial e final que você especifica para
ObjectAnimator
. Por exemplo, é preciso tertargetObject.setPropName(float)
etargetObject.getPropName()
se você construir estaObjectAnimator
:ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- Dependendo da propriedade ou do objeto que você está animando, pode ser necessário chamar o método
invalidate()
em uma visualização para forçar a tela a se redesenhar com o valores animados atualizados. Você faz issoonAnimationUpdate()
o retorno de chamada. Por exemplo, animar a propriedade de cor de um objeto drawable só causa atualizações no tela quando esse objeto for redesenhado. Todos os setters de propriedade em View, comosetAlpha()
esetTranslationX()
invalidar a visualização corretamente para que não seja necessário invalidar a visualização ao chamá-los métodos com novos valores. Para mais informações sobre listeners, consulte a seção sobre Listeners de animação.
Coreografar várias animações com um AnimatorSet
Em muitos casos, você quer exibir uma animação que depende de quando outra começa ou
termina. O sistema Android permite agrupar animações em uma AnimatorSet
, para que você possa especificar se quer iniciar animações.
de forma simultânea, sequencial ou
após um atraso especificado. Também é possível aninhar objetos AnimatorSet
dentro uns dos outros.
O snippet de código abaixo abre a Animator
da seguinte maneira:
- Exibe
bounceAnim
. - Abre
squashAnim1
,squashAnim2
,stretchAnim1
estretchAnim2
ao mesmo tempo. - Exibe
bounceBackAnim
. - Exibe
fadeAnim
.
Kotlin
val bouncer = AnimatorSet().apply { play(bounceAnim).before(squashAnim1) play(squashAnim1).with(squashAnim2) play(squashAnim1).with(stretchAnim1) play(squashAnim1).with(stretchAnim2) play(bounceBackAnim).after(stretchAnim2) } val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 } AnimatorSet().apply { play(bouncer).before(fadeAnim) start() }
Java
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start();
Listeners de animação
Você pode detectar eventos importantes durante a animação com os listeners descritos abaixo.
Animator.AnimatorListener
onAnimationStart()
- Chamado quando a animação começa.onAnimationEnd()
– Chamado quando a animação termina.onAnimationRepeat()
: chamado quando a animação se repete.onAnimationCancel()
: chamado quando a animação é cancelada. Uma animação cancelada também chamaonAnimationEnd()
, independentemente de como foram encerrados.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
: chamado em todos os frames da animação. Ouvir este evento para usam os valores calculados gerados porValueAnimator
durante um animação. Para usar o valor, consulte o objetoValueAnimator
. transmitido no evento para receber o valor animado atual com o métodogetAnimatedValue()
. A implementação o listener será necessário se você usarValueAnimator
.Dependendo de qual propriedade ou objeto você está animando, pode ser necessário chamar
invalidate()
em uma visualização para forçar essa área do para se redesenhar com os novos valores animados. Por exemplo, animar o color de um objeto drawable só causará atualizações na tela quando esse objeto redesenha a si mesmo. Todos os setters de propriedade em View, comosetAlpha()
esetTranslationX()
invalida a visualização. corretamente, para que não seja necessário invalidar a visualização ao chamar esses métodos com novos valores.
-
É possível estender a classe AnimatorListenerAdapter
em vez de
implementar a interface Animator.AnimatorListener
, se você não
implementar todos os métodos da Animator.AnimatorListener
interface gráfica do usuário. A classe AnimatorListenerAdapter
fornece
implementações dos métodos que você pode substituir.
Por exemplo, o snippet de código a seguir cria uma AnimatorListenerAdapter
apenas para o onAnimationEnd()
callback:
Kotlin
ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { balls.remove((animation as ObjectAnimator).target) } }) }
Java
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator)animation).getTarget()); }
Animar mudanças de layout para objetos ViewGroup
O sistema de animação de propriedades fornece a capacidade de animar mudanças em objetos ViewGroup. além de fornecer uma maneira fácil de animar os próprios objetos de visualização.
É possível animar mudanças de layout em um ViewGroup com o
LayoutTransition
. As visualizações em um ViewGroup podem
passam por uma animação que aparece e desaparece quando você os adiciona
removê-los de um ViewGroup ou ao chamar o método
setVisibility()
com
VISIBLE
, INVISIBLE
ou
GONE
. As visualizações restantes no ViewGroup também podem
são animadas em suas novas posições quando você adiciona ou remove Views. É possível definir
as seguintes animações em um objeto LayoutTransition
chamando setAnimator()
.
e transmitir um objeto Animator
com um dos
seguintes constantes LayoutTransition
:
APPEARING
: uma sinalização que indica a animação executada nos itens que estão que aparecem no contêiner.CHANGE_APPEARING
: uma sinalização que indica a animação executada nos itens que estão mudando devido a um novo item que aparece no contêiner.DISAPPEARING
: uma sinalização que indica a animação executada nos itens que estão desaparecendo do contêiner.CHANGE_DISAPPEARING
: uma sinalização que indica a animação executada nos itens que estão mudando porque um item desapareceu do contêiner.
Você pode definir suas próprias animações personalizadas para esses quatro tipos de eventos para personalizar a aparência das transições de layout ou apenas dizer ao sistema de animação para usar as animações padrão.
Para definir o atributo android:animateLayoutchanges
como true
para o
ViewGroup faz o seguinte:
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
Definir este atributo como verdadeiro anima automaticamente as visualizações adicionadas ou removidas da ViewGroup, além das visualizações restantes no ViewGroup.
Animar mudanças de estado de visualização com o StateListAnimator
A classe StateListAnimator
permite definir animadores que são executados quando
o estado de uma visualização muda. Esse objeto se comporta como um wrapper para um
Animator
, chamando essa animação sempre que o objeto
o estado de visualização (como "pressionado" ou "focado").
O StateListAnimator
pode ser definido em um recurso XML com uma raiz
O elemento <selector>
e os elementos filhos <item>
que especificam
um estado de visualização diferente definido pela classe StateListAnimator
. Cada
<item>
contém a definição de um conjunto de animações de propriedade.
Por exemplo, o arquivo a seguir cria um animador de lista de estados que altera a escala x e y. da visualização quando é pressionado:
res/xml/animate_scale.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- the pressed state; increase x and y size to 150% --> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> </set> </item> <!-- the default, non-pressed state; set x and y size to 100% --> <item android:state_pressed="false"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> </set> </item> </selector>
Para anexar o animador da lista de estados a uma visualização, adicione o
android:stateListAnimator
da seguinte forma:
<Button android:stateListAnimator="@xml/animate_scale" ... />
Agora, as animações definidas em animate_scale.xml
são usadas quando o
as mudanças de estado.
Ou, para atribuir um animador de lista de estados a uma visualização no código, use o método
método AnimatorInflater.loadStateListAnimator()
e atribuir o animador a
sua visualização com o método View.setStateListAnimator()
.
Ou, em vez de animar as propriedades da visualização, é possível reproduzir uma animação drawable entre
o estado muda usando AnimatedStateListDrawable
.
Alguns dos widgets do sistema
O Android 5.0 usa essas animações por padrão. O exemplo a seguir mostra como
para definir um AnimatedStateListDrawable
como um recurso XML:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- provide a different drawable for each state--> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- specify a transition --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
Usar um TypeEvaluator
Se quiser animar um tipo que o sistema Android não reconhece, crie o seu próprio
avaliador implementando a interface TypeEvaluator
. Os tipos que
conhecidas pelo sistema Android são int
, float
ou uma cor, que são
compatíveis com os tipos IntEvaluator
, FloatEvaluator
e ArgbEvaluator
;
avaliadores.
Há apenas um método para implementar no TypeEvaluator
do aplicativo, o método evaluate()
. Isso permite
o animador que você está usando para retornar um valor apropriado para a propriedade animada no
o ponto atual da animação. A classe FloatEvaluator
demonstra
como fazer isso:
Kotlin
private class FloatEvaluator : TypeEvaluator<Any> { override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any { return (startValue as Number).toFloat().let { startFloat -> startFloat + fraction * ((endValue as Number).toFloat() - startFloat) } } }
Java
public class FloatEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { float startFloat = ((Number) startValue).floatValue(); return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); } }
Observação:quando ValueAnimator
(ou ObjectAnimator
) é executado, ele calcula uma fração atual decorrida do
animação (um valor entre 0 e 1) e, em seguida, calcula uma versão interpolada disso, dependendo
do interpolador que você está usando. A fração interpolada é o que seu TypeEvaluator
recebe pelo parâmetro fraction
. Portanto, você
não precisam levar em conta o interpolador ao calcular valores animados.
Usar interpoladores
Um interpolador define como valores específicos em uma animação são calculados como uma função de tempo de resposta. Por exemplo, você pode especificar que animações aconteçam linearmente em toda a animação, o que significa que a animação se move de maneira uniforme ao longo do tempo, ou você pode especificar animações a serem usadas tempo não linear, por exemplo, usando aceleração ou desaceleração no início ou no fim do animação.
Os interpoladores no sistema de animação recebem uma fração dos animadores que representam a
tempo decorrido da animação. Os interpoladores modificam essa fração para que coincida com o tipo de
animação que ele pretende fornecer. O sistema Android oferece um conjunto de interpoladores comuns em
o android.view.animation package
. Se nenhum deles atender às suas necessidades
é possível implementar a interface TimeInterpolator
e criar seu
por conta própria.
Por exemplo, veja abaixo uma comparação da forma como o interpolador padrão AccelerateDecelerateInterpolator
e o LinearInterpolator
calculam frações interpoladas.
O LinearInterpolator
não afeta a fração decorrida. O AccelerateDecelerateInterpolator
acelera na animação e
desacelera com esse movimento. Os métodos a seguir definem a lógica desses interpoladores:
AccelerateDecelerateInterpolator
Kotlin
override fun getInterpolation(input: Float): Float = (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f
Java
@Override public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
LinearInterpolator
Kotlin
override fun getInterpolation(input: Float): Float = input
Java
@Override public float getInterpolation(float input) { return input; }
A tabela a seguir representa os valores aproximados calculados por interpoladores para uma animação que dura 1.000 ms:
ms decorridos | Fração decorrida/fração interpolada (linear) | Fração interpolada (acelerar/desacelerar) |
---|---|---|
0 | 0 | 0 |
200 | 0,2 | 0,1 |
400 | 0,4 | 0,345 |
600 | 0,6 | 0,8 |
800 | 0,8 | 0,9 |
1000 | 1 | 1 |
Como mostra a tabela, LinearInterpolator
muda os valores
na mesma velocidade, 0,2 para cada 200 ms decorridos. O AccelerateDecelerateInterpolator
muda os valores mais rapidamente que LinearInterpolator
entre 200 ms e 600 ms e mais lentamente entre 600 ms e 600 ms
1.000 ms.
Especificar frames-chave
Um objeto Keyframe
consiste em um par de tempo/valor que permite definir
um estado específico em um momento específico de uma animação. Cada frame-chave também pode ter o próprio
interpolador para controlar o comportamento da animação no intervalo entre os intervalos anteriores
o tempo do frame-chave e o tempo do frame-chave.
Para instanciar um objeto Keyframe
, é preciso usar um dos objetos de fábrica
métodos, ofInt()
, ofFloat()
ou ofObject()
, para conseguir o tipo apropriado de Keyframe
. Em seguida, você chama
o método de fábrica ofKeyframe()
para
recebe um objeto PropertyValuesHolder
. Depois de ter o objeto, é possível
acesse um animador transmitindo o objeto PropertyValuesHolder
e
o objeto que será animado. O snippet de código a seguir mostra como fazer isso:
Kotlin
val kf0 = Keyframe.ofFloat(0f, 0f) val kf1 = Keyframe.ofFloat(.5f, 360f) val kf2 = Keyframe.ofFloat(1f, 0f) val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2) ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply { duration = 5000 }
Java
Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation); rotationAnim.setDuration(5000);
Animar visualizações
O sistema de animação de propriedades permite uma animação simplificada de objetos e ofertas de visualização. há algumas vantagens em relação ao sistema de animação de visualizações. A visualização de animação transformou objetos View mudando a maneira como eles eram desenhados. Isso foi no contêiner de cada visualização, porque ela não tinha propriedades para manipular. Isso resultava na animação da visualização, mas não mudava em nada o objeto View em si. Isso levou a comportamentos como um objeto ainda existente em seu local original, mesmo que fosse desenhado em outro local na tela. No Android 3.0, as novas propriedades e as métodos getter e setter foram adicionados para eliminar essa desvantagem.
O sistema de animação de propriedades
pode animar as visualizações na tela alterando as propriedades reais nos objetos View. Em
Além disso, as visualizações também chamam automaticamente o método invalidate()
para atualizar a tela sempre que suas propriedades forem alteradas. As novas propriedades na classe View
que facilitam as animações de propriedade são:
translationX
etranslationY
: essas propriedades controlam onde A visualização é localizada como um delta das coordenadas superior e esquerda, que são definidas pelo layout contêiner do Docker.rotation
,rotationX
erotationY
: essas propriedades controlar a rotação em 2D (propriedaderotation
) e em 3D ao redor do ponto de rotação.scaleX
escaleY
: essas propriedades controlam o escalonamento 2D de uma Visualize ao redor do ponto de rotação.pivotX
epivotY
: essas propriedades controlam o local do de eixo, em torno do qual ocorrem as transformações de rotação e escalonamento. Por padrão, a tabela dinâmica está localizado no centro do objeto.x
ey
: são propriedades utilitárias simples para descrever os local final da visualização em seu contêiner, como uma soma dos valores superior e esquerdo e TranslationX e TranslationY.alpha
: representa a transparência Alfa na visualização. Esse valor é 1 (opaca) por padrão, sendo que o valor 0 representa transparência total (não visível).
Para animar uma propriedade de um objeto View, como sua cor ou valor de rotação, você só precisa é criar um animador de propriedade e especificar a propriedade View que você deseja animar. Exemplo:
Kotlin
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)
Java
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Para mais informações sobre como criar animadores, consulte as seções sobre animação com ValueAnimator e ObjectAnimator.
Animar com o ViewPropertyAnimator
O ViewPropertyAnimator
oferece uma maneira simples de animar vários
propriedades de uma View
em paralelo, usando uma única Animator
subjacente
objeto. Ele se comporta de maneira muito parecida com uma ObjectAnimator
, porque modifica a
valores reais das propriedades da visualização, mas é mais eficiente ao animar muitas propriedades em
uma vez. Além disso, o código para usar a ViewPropertyAnimator
é muito
mais concisa e fácil de ler. Os snippets de código a seguir mostram as diferenças no uso de múltiplas
objetos ObjectAnimator
, um único
a ObjectAnimator
e a ViewPropertyAnimator
quando
animando simultaneamente as propriedades x
e y
de uma visualização.
Vários objetos ObjectAnimator
Kotlin
val animX = ObjectAnimator.ofFloat(myView, "x", 50f) val animY = ObjectAnimator.ofFloat(myView, "y", 100f) AnimatorSet().apply { playTogether(animX, animY) start() }
Java
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
Um ObjectAnimator
Kotlin
val pvhX = PropertyValuesHolder.ofFloat("x", 50f) val pvhY = PropertyValuesHolder.ofFloat("y", 100f) ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()
Java
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();
ViewPropertyAnimator
Kotlin
myView.animate().x(50f).y(100f)
Java
myView.animate().x(50f).y(100f);
Para informações mais detalhadas sobre ViewPropertyAnimator
, consulte a página do desenvolvedor Android correspondente
blog
post.
Declarar animações em XML
O sistema de animação de propriedades permite declarar animações de propriedade com XML em vez de fazer programaticamente. Ao definir suas animações em XML, elas podem ser facilmente reutilizadas. em várias atividades e editar a sequência da animação com mais facilidade.
Para distinguir os arquivos de animação que usam as novas APIs de animação de propriedade daqueles que usam a
framework de animação de visualização legado,
No Android 3.1 e versões mais recentes, salve os arquivos XML das animações de propriedade no diretório res/animator/
.
As seguintes classes de animação de propriedade têm suporte à declaração XML com a seguintes tags XML:
ValueAnimator
a<animator>
ObjectAnimator
-<objectAnimator>
AnimatorSet
a<set>
Para encontrar os atributos que podem ser usados na declaração XML, consulte Animação do Google Cloud. O exemplo a seguir exibe os dois conjuntos de animações de objeto sequencialmente, com o primeiro conjunto aninhado reproduzindo duas animações de objeto juntas:
<set android:ordering="sequentially"> <set> <objectAnimator android:propertyName="x" android:duration="500" android:valueTo="400" android:valueType="intType"/> <objectAnimator android:propertyName="y" android:duration="500" android:valueTo="300" android:valueType="intType"/> </set> <objectAnimator android:propertyName="alpha" android:duration="500" android:valueTo="1f"/> </set>
Para executar essa animação, é preciso inflar os recursos XML no código para um objeto AnimatorSet
e definir os objetos de destino para todas as animações
antes de iniciar o conjunto. Por conveniência, a chamada de setTarget()
define um único objeto de destino para todos os filhos de AnimatorSet
. O código abaixo mostra como fazer isso:
Kotlin
(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply { setTarget(myObject) start() }
Java
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.animator.property_animator); set.setTarget(myObject); set.start();
Você também pode declarar um ValueAnimator
em XML, conforme
como mostrado no exemplo a seguir:
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueType="floatType" android:valueFrom="0f" android:valueTo="-100f" />
Para usar o ValueAnimator
anterior no código, faça o seguinte:
precisa inflar o objeto, adicionar uma
AnimatorUpdateListener
,
obter o valor de animação atualizado e usá-lo em uma propriedade de uma das suas visualizações,
conforme mostrado no código a seguir:
Kotlin
(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply { addUpdateListener { updatedAnimation -> textView.translationX = updatedAnimation.animatedValue as Float } start() }
Java
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator); xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } }); xmlAnimator.start();
Para mais informações sobre a sintaxe XML para definir animações de propriedade, consulte Animação recursos.
Possíveis efeitos no desempenho da IU
Os animadores que atualizam a IU causam um trabalho de renderização extra para cada frame em que a animação é executada. Por isso, usar animações que consomem muitos recursos podem afetar negativamente o desempenho do seu app.
O trabalho necessário para animar a IU é adicionado ao estágio de animação do do pipeline de renderização. Você pode descobrir se suas animações afetam o desempenho do app ativando a opção Criação do perfil de renderização de GPU e para monitorar o estágio de animação. Para mais informações, consulte Criação do perfil de renderização de GPU tutorial.