Transition: fundamentos, animação de transições em aplicativos móveis

Autor: IT Sectr Publicado: 2026-03-02 Tempo de leitura: 11 min

Transition é um mecanismo de mudança visual que substitui um conteúdo por outro: telas, fragmentos, views ou estados de interface. Uma transição bem implementada direciona a atenção do usuário, explica a relação entre elementos e torna a navegação intuitiva. De acordo com as Material Design Guidelines (2026), aplicativos com transições bem projetadas mostram 22% mais retenção de usuários na segunda sessão. Saiba mais sobre outros tipos de animação no guia geral de animação.

Principais conclusões

  • Transition — animação de mudança de conteúdo entre telas, fragmentos ou estados.
  • UIView.transition — a principal API para animações de transição no iOS (UIKit).
  • FragmentTransaction.setCustomAnimations — configuração de animações de transição entre Fragment no Android.
  • Transition Framework (android.transition) — sistema de animação declarativo do Android para transições de cena a cena.
  • UIViewControllerAnimatedTransitioning — protocolo iOS para transições personalizadas entre controladores.

O que é Transition?

Transition é uma animação que ocorre ao substituir um estado de interface visual por outro. Ao contrário da Property Animation (animar uma propriedade de um único objeto), Transition gerencia um conjunto completo de mudanças: aparecimento/desaparecimento de elementos, alteração de sua posição, tamanho e propriedades em uma única transição. Transition resolve o problema da mudança suave de conteúdo para que o usuário entenda o que se moveu para onde.

Em plataformas móveis, Transition é usado em três cenários principais: navegação entre telas (push, pop, modal present), mudança de fragmentos (FragmentTransaction do Android) e mudança de estado dentro da tela (expansão de cartão, alternância de abas). Cada cenário exige sua própria abordagem: transições de navegação — UIViewControllerAnimatedTransitioning no iOS ou ActivityOptions no Android, transições dentro da tela — Transition Framework ou UIView.transition.

De acordo com a Apple HIG (2026), a duração de uma transição padrão não deve exceder 400–500 ms — animações mais longas são percebidas como atraso. O Material Design recomenda 300–350 ms para transições móveis. Para elementos grandes (cartões, imagens), o tempo pode aumentar para 500–600 ms sem perda percebida de desempenho.

Tipos de animações de transição

Tipos de transição são divididos em várias categorias dependendo de qual conteúdo muda e como. Tipos básicos: cross-fade — desaparecimento suave de um e aparecimento de outro; slide — uma tela sai, outra entra; scale/zoom — um elemento aumenta, abrindo uma tela de detalhes. Transições combinadas misturam vários efeitos.

Tipo de transiçãoDescriçãoAPI iOSAPI Android
Cross-fadeDesaparecimento: um conteúdo desaparece, outro apareceUIView.transition(with:duration:options:.transitionCrossDissolve)TransitionSet + Fade()
SlideDeslizamento: conteúdo entra/sai horizontal ou verticalmenteCATransition(type: .push, subtype: .fromLeft)Slide() / FragmentTransaction.setCustomAnimations
Scale / ZoomEscala: elemento amplia para tela cheiaUIViewPropertyAnimator com animação de escalaScale() + ActivityOptions.makeScaleUpAnimation
ExplodeExplosão: conteúdo se fragmenta ao desaparecerCATransition(type: .reveal)Explode() (API 21+)
Fade-throughDesaparecimento através de tela branca/pretaUIView.transition(with: .transitionCrossDissolve, com fundo branco)Fade() via ChangeBounds

Regras do Material Design: use um tipo de transição dentro de um único aplicativo para criar uma linguagem visual unificada. Recomendado: slide para navegação entre telas do mesmo nível (master → detalhe), cross-fade para mudança de conteúdo dentro de uma tela (abas, alternância de visualização), scale/zoom para transição de um cartão para uma tela de detalhes (cartão de produto → descrição).

Transições no iOS (Swift)

No iOS, UIView.transition é a maneira mais simples de animar mudanças de conteúdo dentro de uma única View. Ele suporta cross-dissolve, curl-up, curl-down, flip-from-left, flip-from-right. Para transições de navegação entre UIViewController, use UINavigationControllerDelegate com UIViewControllerAnimatedTransitioning — isso dá controle total sobre a animação push/pop.

swift
import UIKit

// UIView.transition: troca de imagem com cross-dissolve
UIView.transition(with: imageView,
    duration: 0.4,
    options: [.transitionCrossDissolve, .curveEaseInOut]
) {
    self.imageView.image = UIImage(named: "new_image")
} completion: { _ in
    print("Transition completed")
}

// UIView.transition: troca de duas views
UIView.transition(from: firstView, to: secondView,
    duration: 0.5,
    options: [.transitionFlipFromRight, .showHideTransitionViews]
) { _ in
    // firstView oculta, secondView exibida
}

// CATransition para camada (sem Auto Layout)
let transition = CATransition()
transition.type = .push
transition.subtype = .fromRight
transition.duration = 0.35
transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
view.layer.add(transition, forKey: "pushTransition")

UIViewPropertyAnimator é uma alternativa moderna para transições personalizadas no iOS 10+. Ao contrário do UIView.transition, o PropertyAnimator suporta pausa, cancelamento e animação reversa, o que é importante para transições interativas (deslizar para voltar). Para animação entre UIViewControllers, use UIPercentDrivenInteractiveTransition junto com PropertyAnimator — este é o padrão padrão para navegação interativa.

Transições no Android (Kotlin)

No Android, FragmentTransaction com setCustomAnimations é a principal maneira de animar transições entre Fragment. Parâmetros: enter (animação de entrada do novo Fragment), exit (animação de saída do Fragment antigo), popEnter e popExit — para navegação de retorno. FragmentTransaction suporta recursos de animação (R.anim) e Transition Framework (R.transition).

kotlin
import androidx.fragment.app.FragmentTransaction
import androidx.transition.TransitionInflater

// FragmentTransaction com animações de recursos
supportFragmentManager.beginTransaction()
    .setCustomAnimations(
        R.anim.slide_in_right,  // enter
        R.anim.slide_out_left,  // exit
        R.anim.slide_in_left,   // popEnter
        R.anim.slide_out_right  // popExit
    )
    .replace(R.id.container, DetailFragment())
    .addToBackStack(null)
    .commit()

// FragmentTransaction com Transition Framework
val detailFragment = DetailFragment()
detailFragment.enterTransition = TransitionInflater.from(this)
    .inflateTransition(R.transition.slide_right)
detailFragment.exitTransition = TransitionInflater.from(this)
    .inflateTransition(R.transition.fade_out)

supportFragmentManager.beginTransaction()
    .replace(R.id.container, detailFragment)
    .addToBackStack(null)
    .commit()

// ActivityOptions: animação ao iniciar uma Activity
val options = ActivityOptions.makeScaleUpAnimation(
    view, 0, 0, view.width, view.height
).toBundle()
startActivity(intent, options)

Melhores práticas do Android: Slide() — para substituição de Fragment na navegação (enter = Slide(Gravity.END), exit = Slide(Gravity.START)). Fade() — para mostrar/esconder sobreposições e diálogos. Explode() — para transições de destaque (excluir um item de uma lista). Para dispositivos antigos (API < 21) use recursos R.anim como fallback. Transition Framework não suporta SurfaceView, TextureView, GLSurfaceView — para vídeo e câmera use apenas animações R.anim.

Transições personalizadas de UIViewController no iOS

UIViewControllerAnimatedTransitioning é um protocolo iOS para criar animações de transição totalmente personalizadas entre controladores. Ele fornece acesso à view contentora (transitionContext.containerView), à view de origem e à view de destino. Combinado com UIPercentDrivenInteractiveTransition, esta abordagem permite criar transições interativas com rolagem por toque.

swift
import UIKit

"> Animador de transição personalizado
class ScaleTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    let isPresenting: Bool

    init(presenting: Bool) { self.isPresenting = presenting }

    func transitionDuration(using ctx: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.4
    }

    func animateTransition(using ctx: UIViewControllerContextTransitioning) {
        guard let toView = ctx.view(forKey: .to),
              let fromView = ctx.view(forKey: .from)
        else { return }

        let container = ctx.containerView
        let initialScale: CGAffineTransform = CGAffineTransform(scaleX: 0.8, y: 0.8)
        let finalFrame = ctx.finalFrame(for: toView)

        if isPresenting {
            toView.transform = initialScale
            toView.alpha = 0
            toView.frame = finalFrame
            container.addSubview(toView)
        }

        UIView.animate(withDuration: transitionDuration(using: ctx),
                       delay: 0,
                       usingSpringWithDamping: 0.7,
                       initialSpringVelocity: 0.3) {
            if self.isPresenting {
                toView.transform = .identity
                toView.alpha = 1
                fromView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
                fromView.alpha = 0
            } else {
                fromView.transform = initialScale
                fromView.alpha = 0
            }
        } completion: { _ in
            fromView.transform = .identity
            ctx.completeTransition(!ctx.transitionWasCancelled)
        }
    }
}

// Aplicação em UINavigationControllerDelegate
extension MainViewController: UINavigationControllerDelegate {
    func navigationController(
        _ nc: UINavigationController,
        animationControllerFor operation: UINavigationController.Operation,
        from: UIViewController, to: UIViewController
    ) -> UIViewControllerAnimatedTransitioning? {
        return ScaleTransitionAnimator(presenting: operation == .push)
    }
}

Transições interativas: adicione um UIPanGestureRecognizer à tela de origem. Quando o gesto for acionado, crie um UIPercentDrivenInteractiveTransition e chame update(CGFloat(percent)). Para cancelar quando o limite não for atingido (geralmente 30%), chame cancel(). Este padrão é usado por padrão no UINavigationController para gestos de pop e no UIScrollView com pagingEnabled. Para gestos personalizados, implemente UIViewControllerInteractiveTransitioning.

Transition Framework no Android: cena a cena

Transition Framework (android.transition) é um sistema de animação declarativo que anima automaticamente as mudanças entre duas cenas (Scene). Uma cena é um conjunto de Views com um estado específico. Ao passar da Cena A para a Cena B, o Transition Framework analisa a diferença e anima: mudança de posição (ChangeBounds), mudança de tamanho (ChangeClipBounds, ChangeTransform), aparecimento (Fade) e desaparecimento (Fade).

kotlin
import android.transition.Scene
import android.transition.TransitionManager
import android.transition.TransitionSet
import android.transition.AutoTransition
import android.transition.ChangeBounds
import android.transition.Fade

// TransitionSet: combinação de ChangeBounds + Fade
val transition = TransitionSet().apply {
    ordering = TransitionSet.ORDERING_TOGETHER
    addTransition(ChangeBounds())
    addTransition(Fade(Fade.IN))
    duration = 400L
    interpolator = FastOutSlowInInterpolator()
}

// Transição entre cenas em um ViewGroup
val sceneRoot = findViewById<ViewGroup>(R.id.scene_root)
val scene1 = Scene.getSceneForLayout(sceneRoot, R.layout.scene_initial)
val scene2 = Scene.getSceneForLayout(sceneRoot, R.layout.scene_expanded)

"> AutoTransition sem configuração manual
TransitionManager.go(scene2, AutoTransition().apply {
    duration = 350L
})

// TransitionManager.beginDelayedTransition — sem cenas
TransitionManager.beginDelayedTransition(sceneRoot, ChangeBounds())
itemView.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
itemView.requestLayout() itemView.requestLayout() "> A alteração do layout é animada automaticamente

ChangeBounds é a transição mais usada no Android, anima mudanças de posição e tamanho da View. ChangeTransform anima rotação e escala. ChangeImageTransform — para animação de ImageView (centerCrop → fitCenter). Para transições complexas com mudanças na estrutura hierárquica, use TransitionSet com ordering = ORDERING_SEQUENTIAL (animações executam em sequência, não em paralelo). De acordo com a documentação do Android Developers (2026), o Transition Framework suporta todas as Views padrão, mas não suporta animação de superfície (SurfaceView, TextureView, VideoView).

Perguntas frequentes

Qual a diferença entre Transition e Animation?

Animation — anima propriedades de um único objeto (alpha, translation, scale). Transition — anima a mudança de um conjunto de objetos ou estados (fragment → fragment, scene → scene). Transition gerencia múltiplas mudanças simultaneamente: aparecimento, desaparecimento, movimento, mudança de tamanho — e anima automaticamente a diferença entre dois estados. Animation requer gerenciamento manual de cada propriedade.

Como fazer uma transição suave entre fragmentos Android?

Use FragmentTransaction.setCustomAnimations com Transition Framework: fragment1.exitTransition = Fade(Fade.OUT), fragment2.enterTransition = Slide(Gravity.END). Para sequenciamento: setReorderingAllowed(true) — os fragmentos serão reordenados para uma transição paralela suave. Para casos simples, slide_in_right / slide_out_left de R.anim é suficiente. Para navegação de retorno, especifique popEnter e popExit.

Transition Framework não anima alteração de altura da View — o que fazer?

Transition Framework anima apenas propriedades que não acionam recálculo de layout. Para animação de altura, use ChangeBounds — ele anima automaticamente as mudanças de limites da View entre dois estados de layout. Chame TransitionManager.beginDelayedTransition(viewGroup, ChangeBounds()) antes de alterar LayoutParams. Se a altura mudar via WRAP_CONTENT, certifique-se de que layout_height difere antes e depois — ChangeBounds não funcionará se ambos os estados forem match_parent.

Como criar uma transição personalizada em SwiftUI?

Use o modificador .transition() com AnyTransition: .transition(.move(edge: .trailing).combined(with: .opacity)). Para transições personalizadas, implemente AnyTransition.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)). Para animação dentro do NavigationStack, use .navigationTransition(.slide) no iOS 18+. SwiftUI não suporta UIViewControllerAnimatedTransitioning — apenas transições declarativas via AnyTransition.

Como medir o desempenho do Transition?

Use Profile GPU Rendering (Android) ou Core Animation Instrument (iOS). Para Android, ative o Transition Profiling via adb shell setprop debug.transition.profiling 1 — os logs mostrarão a duração de cada estágio da transição. No iOS, ative Slow Animations no simulador. Métricas alvo: duração < 400 ms, FPS >= 55, frame drops — não mais que 2 por transição. Para cenas complexas com 15+ Views animadas simultaneamente, use ChangeBounds com duração de 300 ms.

Resumo

  • Transition — animação de mudança de conteúdo entre telas, fragmentos ou estados de interface.
  • UIView.transition (iOS) — API básica para transições cross-dissolve, flip, curl dentro de uma View.
  • UIViewControllerAnimatedTransitioning (iOS) — protocolo para transições personalizadas entre controladores.
  • FragmentTransaction.setCustomAnimations (Android) — animação de transição entre Fragment.
  • Transition Framework (android.transition) — sistema de cenas declarativo: ChangeBounds, Fade, Slide, Explode.
  • Duração recomendada: 300–400 ms para móvel, até 600 ms para elementos grandes.
  • Um tipo de transição por aplicativo para linguagem visual unificada (Material Design).

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também