page.title=Como definir animações personalizadas @jd:body <div id="tb-wrapper"> <div id="tb"> <h2>Esta lição ensina a</h2> <ol> <li><a href="#Touch">Personalizar feedback de toque</a></li> <li><a href="#Reveal">Usar o efeito de revelação</a></li> <li><a href="#Transitions">Personalizar transições de atividades</a></li> <li><a href="#ViewState">Animar mudança de estado da visualização</a></li> <li><a href="#AnimVector">Animar desenháveis de vetor</a></li> </ol> <h2>Você também deve ler</h2> <ul> <li><a href="http://www.google.com/design/spec">Especificações do Material Design</a></li> <li><a href="{@docRoot}design/material/index.html">Material Design no Android</a></li> </ul> </div> </div> <p>As animações no Material Design dão feedback aos usuários sobre as ações deles e fornecem continuidade visual à medida que interagem com o seu aplicativo. O tema do Material fornece algumas animações padrão para botões e transições de atividades e o Android 5.0 (API de nível 21) e posteriores permitem a personalização dessas animações e a criação de novas:</p> <ul> <li>Feedback de toque</li> <li>Revelação circular</li> <li>Transições de atividades</li> <li>Movimento curvado</li> <li>Mudanças de estado da visualização</li> </ul> <h2 id="Touch">Personalizar feedback de toque</h2> <p>Os feedbacks de toque no Material Design fornecem confirmação visual instantânea no ponto de contato quando os usuários interagem com elementos da interface do usuário. As animações de feedback de toque padrão para botões usam a nova classe {@link android.graphics.drawable.RippleDrawable}, que passa por transições entre diferentes estados com um efeito de ondulação.</p> <p>Na maioria dos casos, você deve aplicar essa funcionalidade no XML de visualização especificando o segundo plano da visualização como:</p> <ul> <li><code>?android:attr/selectableItemBackground</code> para uma ondulação delimitada.</li> <li><code>?android:attr/selectableItemBackgroundBorderless</code> para uma ondulação que se estenda além da visualização. Ele será desenhado sobre e delimitado pelo pai mais próximo da visualização com um segundo plano não nulo.</li> </ul> <p class="note"><strong>Observação:</strong> <code>selectableItemBackgroundBorderless</code> é um novo atributo introduzido na API de nível 21.</p> <p>Alternativamente, você pode definir um {@link android.graphics.drawable.RippleDrawable} como um recurso XML usando o elemento <code>ripple</code>.</p> <p>Você pode atribuir uma cor para objetos {@link android.graphics.drawable.RippleDrawable}. Para alterar a cor do feedback de toque padrão, use o atributo <code>android:colorControlHighlight</code> do tema.</p> <p>Para obter mais informações, consulte a referência de API para a classe {@link android.graphics.drawable.RippleDrawable}.</p> <h2 id="Reveal">Usar o efeito de revelação</h2> <p>Revelar animações fornece continuidade visual aos usuários ao exibir ou esconder um grupo de elementos da interface do usuário. O método {@link android.view.ViewAnimationUtils#createCircularReveal ViewAnimationUtils.createCircularReveal()} permite animar um círculo de recorte para revelar ou ocultar uma visualização.</p> <p>Para revelar uma visualização anteriormente invisível usando esse efeito:</p> <pre> // previously invisible view View myView = findViewById(R.id.my_view); // get the center for the clipping circle int cx = (myView.getLeft() + myView.getRight()) / 2; int cy = (myView.getTop() + myView.getBottom()) / 2; // get the final radius for the clipping circle int finalRadius = Math.max(myView.getWidth(), myView.getHeight()); // create the animator for this view (the start radius is zero) Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius); // make the view visible and start the animation myView.setVisibility(View.VISIBLE); anim.start(); </pre> <p>Para esconder uma visualização anteriormente visível usando esse efeito:</p> <pre> // previously visible view final View myView = findViewById(R.id.my_view); // get the center for the clipping circle int cx = (myView.getLeft() + myView.getRight()) / 2; int cy = (myView.getTop() + myView.getBottom()) / 2; // get the initial radius for the clipping circle int initialRadius = myView.getWidth(); // create the animation (the final radius is zero) Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0); // make the view invisible when the animation is done anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); myView.setVisibility(View.INVISIBLE); } }); // start the animation anim.start(); </pre> <h2 id="Transitions">Personalizar transições de atividades</h2> <!-- shared transition video --> <div style="width:290px;margin-left:35px;float:right"> <div class="framed-nexus5-port-span-5"> <video class="play-on-hover" autoplay=""> <source src="{@docRoot}design/material/videos/ContactsAnim.mp4"> <source src="{@docRoot}design/material/videos/ContactsAnim.webm"> <source src="{@docRoot}design/material/videos/ContactsAnim.ogv"> </video> </div> <div style="font-size:10pt;margin-left:20px;margin-bottom:30px"> <p class="img-caption" style="margin-top:3px;margin-bottom:10px"><strong>Figura 1</strong> - uma transição com elementos compartilhados.</p> <em>Para reproduzir o filme, clique na tela do dispositivo</em> </div> </div> <p>As transições de atividades em aplicativos com Material Design fornecem conexões visuais entre estados diferentes por meio de movimentos e transformações entre elementos comuns. Você pode especificar animações personalizadas para transições de entrada e de saída e para transições de elementos compartilhados entre atividades.</p> <ul> <li>Uma transição de <strong>entrada</strong> determina como as visualizações em uma atividade entram em cena. Por exemplo, na transição de entrada <em>explodir</em>, as visualizações entram em cena por fora e voam em direção ao centro da tela.</li> <li>Uma transição de <strong>saída</strong> determina como as visualizações em uma atividade saem de cena. Por exemplo, na transição de saída <em>explodir</em>, as visualizações saem de cena a partir do centro.</li> <li>Uma transição de <strong>elementos compartilhados</strong> determina como as visualizações compartilhadas entre duas atividades fazem transição entre essas atividades. Por exemplo, se duas atividades têm a mesma imagem em posições e tamanhos diferentes, a transição de elemento compartilhado <em>changeImageTransform</em> converte e dimensiona a imagem suavemente entre essas atividades.</li> </ul> <p>O Android 5.0 (API de nível 21) é compatível com estas transições de entrada e de saída:</p> <ul> <li><em>explodir</em> - move as visualizações para dentro ou para fora partindo do centro da cena.</li> <li><em>deslizar</em> - move as visualizações para dentro ou para fora partindo de um dos cantos da cena.</li> <li><em>esmaecer</em> - adiciona ou remove uma visualização de uma cena alterando a opacidade.</li> </ul> <p>Qualquer transição que amplie a classe {@link android.transition.Visibility} é suportada como uma transição de entrada ou de saída. Para obter mais informações, consulte a referência de API para a classe {@link android.transition.Transition}.</p> <p>O Android 5.0 (API de nível 21) também é compatível com estas transições de elementos compartilhados:</p> <ul> <li><em>changeBounds</em> - anima as mudanças das visualizações desejadas em limites do layout.</li> <li><em>changeBounds</em> - anima as mudanças das visualizações desejadas em limites de corte.</li> <li><em>changeBounds</em> - anima as mudanças das visualizações desejadas em escala e rotação.</li> <li><em>changeImageTransform</em> - anima as mudanças das imagens desejadas em tamanho e escala.</li> </ul> <p>Ao habilitar as transições de atividades no seu aplicativo, a transição de esmaecimento cruzado padrão é ativada entre as atividades de entrada e saída.</p> <img src="{@docRoot}training/material/images/SceneTransition.png" alt="" width="600" height="405" style="margin-top:20px" /> <p class="img-caption"> <strong>Figura 2</strong> - uma transição de cena com um elemento compartilhado. </p> <h3>Especificar transições de atividades</h3> <p>Primeiro, habilite as transições de conteúdo da janela com o atributo <code>android:windowContentTransitions</code> ao definir um estilo herdado do tema do Material. Você também pode especificar transições de entrada, saída e elemento compartilhado na definição de estilo:</p> <pre> <style name="BaseAppTheme" parent="android:Theme.Material"> <!-- enable window content transitions --> <item name="android:windowContentTransitions">true</item> <!-- specify enter and exit transitions --> <item name="android:windowEnterTransition">@transition/explode</item> <item name="android:windowExitTransition">@transition/explode</item> <!-- specify shared element transitions --> <item name="android:windowSharedElementEnterTransition"> @transition/change_image_transform</item> <item name="android:windowSharedElementExitTransition"> @transition/change_image_transform</item> </style> </pre> <p>A transição <code>change_image_transform</code> nesse exemplo é definida a seguir:</p> <pre> <!-- res/transition/change_image_transform.xml --> <!-- (see also Shared Transitions below) --> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <changeImageTransform/> </transitionSet> </pre> <p>O elemento <code>changeImageTransform</code> corresponde à classe {@link android.transition.ChangeImageTransform}. Para obter mais informações, consulte a referência de API para {@link android.transition.Transition}.</p> <p>Para habilitar transições de conteúdo da janela no código como alternativa, chame o método {@link android.view.Window#requestFeature Window.requestFeature()}:</p> <pre> // inside your activity (if you did not enable transitions in your theme) getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); // set an exit transition getWindow().setExitTransition(new Explode()); </pre> <p>Para especificar transições no código, chame os métodos a seguir com um objeto {@link android.transition.Transition}:</p> <ul> <li>{@link android.view.Window#setEnterTransition Window.setEnterTransition()}</li> <li>{@link android.view.Window#setExitTransition Window.setExitTransition()}</li> <li>{@link android.view.Window#setSharedElementEnterTransition Window.setSharedElementEnterTransition()}</li> <li>{@link android.view.Window#setSharedElementExitTransition Window.setSharedElementExitTransition()}</li> </ul> <p>Os métodos {@link android.view.Window#setExitTransition setExitTransition()} e {@link android.view.Window#setSharedElementExitTransition setSharedElementExitTransition()} definem a transição de saída para a atividade de chamada. Os métodos {@link android.view.Window#setEnterTransition setEnterTransition()} e {@link android.view.Window#setSharedElementEnterTransition setSharedElementEnterTransition()} definem a transição de entrada para a atividade chamada.</p> <p>Para obter o efeito completo de uma transição, você deve habilitar as transições de conteúdo da janela tanto na atividade chamada quanto na atividade de chamada. Caso contrário, a atividade de chamada acionará a transição de saída, mas você verá uma transição de janela (como dimensionamento ou esmaecimento).</p> <p>Para iniciar uma transição de entrada o mais cedo possível, use o método {@link android.view.Window#setAllowEnterTransitionOverlap Window.setAllowEnterTransitionOverlap()} na atividade chamada. Isso faz com que haja transições de entrada mais dramáticas.</p> <h3>Iniciar uma atividade usando transições</h3> <p>Se você habilita as transições e define uma transição de saída para uma atividade, a transição será ativada ao iniciar outra atividade, como a seguir:</p> <pre> startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle()); </pre> <p>Se você configurou uma transição de entrada para a segunda atividade, a transição também será ativada quando a atividade for iniciada. Para desabilitar as transições ao iniciar outra atividade, forneça um pacote de opções <code>null</code>.</p> <h3>Iniciar uma atividade com um elemento compartilhado</h3> <p>Para criar uma animação de transição de tela entre duas atividades que têm um elemento compartilhado:</p> <ol> <li>Habilite transições de conteúdo da janela no tema.</li> <li>Especifique uma transição de elementos compartilhados no estilo.</li> <li>Defina a transição como um recurso XML.</li> <li>Atribua um nome comum aos elementos compartilhados em ambos os layouts com o atributo <code>android:transitionName</code>.</li> <li>Use o método {@link android.app.ActivityOptions#makeSceneTransitionAnimation ActivityOptions.makeSceneTransitionAnimation()}.</li> </ol> <pre> // get the element that receives the click event final View imgContainerView = findViewById(R.id.img_container); // get the common element for the transition in this activity final View androidRobotView = findViewById(R.id.image_small); // define a click listener imgContainerView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(this, Activity2.class); // create the transition animation - the images in the layouts // of both activities are defined with android:transitionName="robot" ActivityOptions options = ActivityOptions .makeSceneTransitionAnimation(this, androidRobotView, "robot"); // start the new activity startActivity(intent, options.toBundle()); } }); </pre> <p>Para obter visualizações dinâmicas compartilhadas geradas no código, use o método {@link android.view.View#setTransitionName View.setTransitionName()} para especificar um nome de elemento comum em ambas as atividades.</p> <p>Para reverter a animação de transição de cena ao finalizar a segunda atividade, chame o método {@link android.app.Activity#finishAfterTransition Activity.finishAfterTransition()} em vez de {@link android.app.Activity#finish Activity.finish()}.</p> <h3>Iniciar uma atividade com diversos elementos compartilhados</h3> <p>Para criar uma animação de transição de cena entre duas atividades que têm mais de um elemento compartilhado, defina os elementos compartilhados em ambos os layouts com o atributo <code>android:transitionName</code> (ou use o método {@link android.view.View#setTransitionName View.setTransitionName()} em ambas as atividades) e crie um objeto {@link android.app.ActivityOptions}, como a seguir:</p> <pre> ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view1, "agreedName1"), Pair.create(view2, "agreedName2")); </pre> <h2 id="CurvedMotion">Usar movimento curvado</h2> <p>As animações no Material Design dependem das curvas para obter padrões de interpolação de tempo e de movimentos espaciais. Com o Android 5.0 (API de nível 21) e posteriores, você pode definir padrões de curvas de temporização personalizada e de movimentos curvados para animações.</p> <p>A classe {@link android.view.animation.PathInterpolator} é um novo interpolador baseado em uma curva Bézier ou em um objeto {@link android.graphics.Path}. Esse interpolador especifica uma curva de movimento em um quadrado de 1x1, com pontos de ancoragem em (0,0) e (1,1) e pontos de controle conforme especificado usando os argumentos do construtor. Você também pode definir um interpolador de caminho como um recurso XML:</p> <pre> <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:controlX1="0.4" android:controlY1="0" android:controlX2="1" android:controlY2="1"/> </pre> <p>O sistema fornece recursos XML para três curvas básicas na especificação do Material Design:</p> <ul> <li><code>@interpolator/fast_out_linear_in.xml</code></li> <li><code>@interpolator/fast_out_slow_in.xml</code></li> <li><code>@interpolator/linear_out_slow_in.xml</code></li> </ul> <p>Você pode passar um objeto {@link android.view.animation.PathInterpolator} para o método {@link android.animation.Animator#setInterpolator Animator.setInterpolator()}.</p> <p>A classe {@link android.animation.ObjectAnimator} tem novos construtores que permitem a animação de coordenadas ao longo de um caminho usando duas ou mais propriedades simultaneamente. Por exemplo, o animador a seguir usa um objeto {@link android.graphics.Path} para animar as propriedades X e Y de uma visualização:</p> <pre> ObjectAnimator mAnimator; mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); ... mAnimator.start(); </pre> <h2 id="ViewState">Animar mudança de estado da visualização</h2> <p>A classe {@link android.animation.StateListAnimator} permite a definição de animadores que são executados quando o estado de uma visualização muda. O exemplo a seguir mostra como definir um {@link android.animation.StateListAnimator} como um recurso XML:</p> <pre> <!-- animate the translationZ property of a view when pressed --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="@android:integer/config_shortAnimTime" android:valueTo="2dp" android:valueType="floatType"/> <!-- you could have other objectAnimator elements here for "x" and "y", or other properties --> </set> </item> <item android:state_enabled="true" android:state_pressed="false" android:state_focused="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="0" android:valueType="floatType"/> </set> </item> </selector> </pre> <p>Para anexar animações de estado de visualização personalizadas a uma visualização, defina um animador usando o elemento <code>selector</code> em um arquivo de recurso XML, como nesse exemplo, e atribua-o à visualização com o atributo <code>android:stateListAnimator</code>. Para atribuir um animador de lista de estado a uma visualização no código, use o método {@link android.animation.AnimatorInflater#loadStateListAnimator AnimationInflater.loadStateListAnimator()} e atribua o animador à visualização com o método {@link android.view.View#setStateListAnimator View.setStateListAnimator()}.</p> <p>Quando o tema amplia o tema do Material, os botões têm uma animação Z por padrão. Para evitar esse comportamento nos botões, defina o atributo <code>android:stateListAnimator</code> como <code>@null</code>.</p> <p>A classe {@link android.graphics.drawable.AnimatedStateListDrawable} permite a criação de desenháveis que exibem animações entre mudanças de estado da visualização associada. Alguns dos widgets de sistema no Android 5.0 usam essas animações por padrão. O exemplo a seguir mostra como definir um {@link android.graphics.drawable.AnimatedStateListDrawable} como um recurso XML:</p> <pre> <!-- 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> </pre> <h2 id="AnimVector">Animar desenháveis de vetor</h2> <p><a href="{@docRoot}training/material/drawables.html#VectorDrawables">Desenháveis de vetor</a> são dimensionáveis sem perder definição. A classe {@link android.graphics.drawable.AnimatedVectorDrawable} permite a animação de propriedades de um desenhável de vetor.</p> <p>Você normalmente define desenháveis de vetor animados em três arquivos XML:</p> <ul> <li>Um desenhável de vetor com o elemento <code><vector></code> em <code>res/drawable/</code></li> <li>Um desenhável de vetor animado com o elemento <code><animated-vector></code> em <code>res/drawable/</code></li> <li>Um ou mais animadores de objeto com o elemento <code><objectAnimator></code> em <code>res/anim/</code></li> </ul> <p>Desenháveis de vetor animados podem animar os atributos dos elementos <code><group></code> e <code><path></code>. Os elementos <code><group></code> definem um conjunto de caminhos ou subgrupos e o elemento <code><path></code> define caminhos a serem desenhados.</p> <p>Ao definir um desenhável de vetor que você queira animar, use o atributo <code>android:name</code> para atribuir um nome único a grupos e caminhos para poder referenciá-los nas definições do animador. Por exemplo:</p> <pre> <!-- res/drawable/vectordrawable.xml --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="64dp" android:width="64dp" android:viewportHeight="600" android:viewportWidth="600"> <group <strong>android:name="rotationGroup"</strong> android:pivotX="300.0" android:pivotY="300.0" android:rotation="45.0" > <path <strong>android:name="v"</strong> android:fillColor="#000000" android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> </group> </vector> </pre> <p>A definição de desenhável de vetor animado se refere a grupos e caminhos no desenhável de vetor pelos respectivos nomes:</p> <pre> <!-- res/drawable/animvectordrawable.xml --> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vectordrawable" > <target android:name="rotationGroup" android:animation="@anim/rotation" /> <target android:name="v" android:animation="@anim/path_morph" /> </animated-vector> </pre> <p>As definições de animação representam objetos {@link android.animation.ObjectAnimator} ou {@link android.animation.AnimatorSet}. O primeiro animador nesse exemplo gira o grupo desejado em 360º:</p> <pre> <!-- res/anim/rotation.xml --> <objectAnimator android:duration="6000" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" /> </pre> <p>O segundo animador nesse exemplo transforma a forma do caminho do desenhável de vetor. Ambos os caminhos devem ser compatíveis com a transformação: eles precisam ter o mesmo número de comandos e de parâmetros para cada comando.</p> <pre> <!-- res/anim/path_morph.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="3000" android:propertyName="pathData" android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z" android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z" android:valueType="pathType" /> </set> </pre> <p>Para obter mais informações, consulte a referência de API para {@link android.graphics.drawable.AnimatedVectorDrawable}.</p>