Timeline — fundamentos, gerenciamento de tempo de animação em aplicativos

Autor: IT Sectr Publicado: 2026-03-02 Tempo de leitura: 8 min
Timeline (linha do tempo) é um conceito fundamental de animação que determina quanto tempo uma animação dura, em que ordem suas etapas são executadas e como o tempo é mapeado para o progresso. No desenvolvimento de aplicativos móveis, a linha do tempo é gerenciada através de duração (duration), atraso (delay), repetições (repeat) e carimbos de tempo. No iOS, a linha do tempo da animação é implementada via CACurrentMediaTime e CAMediaTiming, enquanto no Android usa ValueAnimator e Animator com os parâmetros duration, startDelay e repeatCount. De acordo com Apple Documentation, o controle preciso da linha do tempo é criticamente importante para a sincronização de animações: uma dessincronização de apenas 16 ms (um quadro a 60fps) é percebida pelo usuário como trepidação. Na IT Sectr, padronizamos o uso da linha do tempo através do ValueAnimator no Android e CABasicAnimation com CAMediaTiming no iOS — isso garante um gerenciamento uniforme do tempo em todos os projetos.

Pontos Principais

  • Timeline — o conceito de gerenciamento de tempo de animação: duration, delay, repeat, mapeamento do tempo para o progresso.
  • CAMediaTiming — protocolo iOS Core Animation para gerenciamento da linha do tempo: duration, beginTime, repeatCount, speed, timeOffset.
  • ValueAnimator — a classe central do Android para trabalhar com a linha do tempo de animação através de duration, startDelay, repeatCount.
  • CACurrentMediaTime — função iOS para obter o tempo absoluto em segundos, usada para sincronização.
  • TimeInterval — um tipo de dado no iOS (Double) que representa um intervalo de tempo para cálculos de animação.

O que é Timeline?

Timeline é um modelo de tempo de animação que define quando uma animação começa, quanto tempo dura e como a progressão do tempo é transformada em mudanças do parâmetro animado. Ao contrário da animação quadro a quadro (frame-by-frame), onde cada quadro é definido manualmente, a animação por linha do tempo é descrita por parâmetros: duration — duração total, startDelay — atraso antes do início, repeatCount — número de repetições, e timingFunction — a curva de velocidade.

A linha do tempo opera em um espaço normalizado [0, 1] — tempo local ou progresso. O valor zero corresponde ao início da animação, um à conclusão. Uma função de easing (suavização) converte o tempo local linear em progresso real da animação. Se repeatCount > 1, a linha do tempo cicla (RESTART) ou inverte (REVERSE). No iOS, CAMediaTiming adiciona speed (taxa de reprodução, >1 acelera) e timeOffset (deslocamento da linha do tempo). No Android, Animator usa setCurrentPlayTime() para controle direto da posição na linha do tempo. De acordo com Material Design, animações com menos de 100 ms não são percebidas como animações, enquanto as com mais de 500 ms começam a irritar. A duração ideal para animações de interface é de 200–350 ms.

Timeline no iOS: CAMediaTiming e CACurrentMediaTime

No iOS, o gerenciamento da linha do tempo da animação é feito através do protocolo CAMediaTiming, implementado por CAAnimation e CALayer. Ele fornece as propriedades: duration (em segundos), beginTime (tempo de início relativo à linha do tempo pai), repeatCount (número de repetições), repeatDuration (duração total das repetições), autoreverses (reversão automática), fillMode (comportamento antes/depois da animação), speed (taxa de reprodução) e timeOffset (deslocamento da linha do tempo).

CACurrentMediaTime() é uma função que retorna o tempo absoluto em segundos desde a última reinicialização do dispositivo. É usada como carimbo de tempo base para sincronizar múltiplas animações: defina beginTime = CACurrentMediaTime() + offset para iniciar um grupo de animações com atraso preciso. CAMediaTiming também suporta hierarquia de linha do tempo — uma camada pai pode acelerar/desacelerar todas as animações filhas através da propriedade speed. No UIKit, UIViewPropertyAnimator (iOS 10+) abstrai a linha do tempo através das propriedades duration, delay e callbacks startAnimation/pauseAnimation/stopAnimation. No SwiftUI, a estrutura Animation fornece duration como parte da especificação da animação, mas o controle direto da linha do tempo está oculto — para linha do tempo personalizada, use TimelineView (iOS 15+) com um scheduler personalizado.

Timeline no Android: Animator e duration

No Android, o gerenciamento da linha do tempo é centralizado na classe Animator e suas subclasses (ValueAnimator, ObjectAnimator). As principais propriedades da linha do tempo são: duration (em milissegundos), startDelay (atraso antes do início), repeatCount (número de repetições), repeatMode (RESTART ou REVERSE). O método setCurrentPlayTime(long) permite navegar pela linha do tempo para qualquer posição arbitrária.

ValueAnimator adiciona uma camada de abstração: gera valores de 0 a 1 (tempo normalizado) com base na duration e os passa para TimeInterpolator. AnimatorSet permite combinar vários Animators em uma única linha do tempo com execução sequencial (playSequentially) ou paralela (playTogether). No Jetpack Compose, a linha do tempo é gerenciada através de AnimationSpec: tween (durationMillis, delayMillis, easing), spring (dampingRatio, stiffness) e keyframes (pontos na linha do tempo com easing personalizado para cada segmento). Compose AnimatedContent usa uma linha do tempo para transitionSpec — o desenvolvedor descreve como o conteúdo aparece/desaparece com deslocamentos temporais. De acordo com Android Performance, a linha do tempo da animação deve ser um múltiplo de 16 ms (ciclo vsync) para 60fps — duração incorreta pode causar queda de quadros devido à incompatibilidade com a taxa de atualização da tela.

Composição de Animações no Tempo

A linha do tempo torna-se especialmente importante ao compor múltiplas animações. Três padrões básicos: cascata — as animações iniciam sequencialmente com um deslocamento (cada próxima começa após um offset da anterior), paralelo — todas as animações começam simultaneamente com a mesma linha do tempo, e escalonado (stagger) — as animações começam com sobreposição (a segunda começa antes da primeira terminar).

No iOS, a cascata é implementada através de beginTime de cada CAAnimation = beginTime anterior + duration anterior. Para escalonamento, CAAnimationGroup é usado com diferentes valores de beginTime em animações aninhadas. No Android, AnimatorSet suporta playSequentially e playTogether; o escalonamento é criado definindo startDelay para cada Animator. No Compose, AnimatedVisibility com enter/exitTransition usa escalonamento na variante staggerChildren para aparecimento em cascata de itens de lista. Na WWDC e Google I/O 2024, ambas as plataformas apresentaram ferramentas de visualização de linha do tempo: Xcode Animations Inspector e Android Studio Animations Timeline — eles mostram a linha do tempo real e quadros perdidos em tempo real.

Exemplos de Código

iOS: CABasicAnimation com CAMediaTiming

Um exemplo de animação com linha do tempo personalizada: atraso de 0,3 s, duração de 0,6 s, autoreverse e repetição infinita. CAMediaTiming controla todos os parâmetros temporais.

swift
import UIKit

func breathingAnimation(layer: CALayer) {
    let animation = CABasicAnimation(keyPath: "opacity")
    animation.duration = 0.6
    animation.beginTime = CACurrentMediaTime() + 0.3
    animation.fromValue = 1.0
    animation.toValue = 0.3
    animation.autoreverses = true
    animation.repeatCount = .infinity
    animation.speed = 1.0
    animation.fillMode = .both

    layer.add(animation, forKey: "breathing")
}

beginTime = CACurrentMediaTime() + 0,3 fornece um atraso de 300 ms. autoreverses = true faz a animação executar em reverso após cada ciclo. repeatCount = .infinity cria um loop infinito do efeito “respiração”. speed = 1,0 — velocidade normal; acelere a animação 2x com um valor de 2,0.

iOS: TimelineView para Linha do Tempo Personalizada

SwiftUI TimelineView (iOS 15+) fornece acesso à linha do tempo do sistema para animação personalizada. A View atualiza a cada tick do scheduler.

swift
import SwiftUI

struct TimelineViewExample: View {
    var body: some View {
        TimelineView(.periodic(from: .now, by: 0.1)) { context in
            let seconds = context.date.timeIntervalSinceReferenceDate
            let phase = sin(seconds * 2 * .pi)

            Circle()
                .fill(Color.blue)
                .frame(width: 60 + 30 * phase)
                .animation(.linear(duration: 0), value: phase)
        }
    }
}

TimelineView com scheduler .periodic gera ticks a cada 0,1 s. No closure, context.date é a hora atual, que é convertida em uma fase de onda senoidal. O tamanho do círculo pulsa a uma frequência de 1 Hz. TimelineView é a única maneira de criar uma animação com sua própria linha do tempo no SwiftUI sem a API Animation.

Android: ValueAnimator com Linha do Tempo Personalizada

ValueAnimator com controle total da linha do tempo: atraso, duração, repetição. O método setCurrentPlayTime permite saltar ao longo da linha do tempo.

kotlin
import android.animation.ValueAnimator
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.View

fun View.timelineAnimation() {
    ValueAnimator.ofFloat(0f, 1f).apply {
        duration = 400
        startDelay = 200
        repeatCount = 2
        repeatMode = ValueAnimator.REVERSE
        interpolator = AccelerateDecelerateInterpolator()

        addUpdateListener { animator ->
            val progress = animator.animatedFraction
            alpha = progress
            translationX = progress * 100f
        }

        start()
    }
}

startDelay = 200 ms — atraso antes do início. repeatMode = REVERSE retorna a animação ao valor inicial. animatedFraction dá o progresso de 0 a 1 considerando repeatMode. addUpdateListener dispara a cada quadro (normalmente 16 ms). Use pause() / resume() para pausar.

Android: AnimatorSet para Composição de Linha do Tempo

AnimatorSet permite criar linhas do tempo complexas a partir de múltiplas animações. O exemplo demonstra execução sequencial com sobreposição (stagger).

kotlin
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.view.View

fun View.staggerAnimation() {
    val fadeIn = ObjectAnimator.ofFloat(this, "alpha", 0f, 1f).apply {
        duration = 300
    }
    val slideUp = ObjectAnimator.ofFloat(this, "translationY", 100f, 0f).apply {
        duration = 400
        startDelay = 100
    }
    val scale = ObjectAnimator.ofFloat(this, "scaleX", 0.8f, 1f).apply {
        duration = 250
        startDelay = 200
    }

    AnimatorSet().apply {
        playTogether(fadeIn, slideUp, scale)
        start()
    }
}

playTogether inicia todas as animações em paralelo, mas cada uma tem seu próprio startDelay — isso cria um efeito escalonado: fadeIn começa primeiro (0 ms), slideUp após 100 ms, scale após 200 ms. A linha do tempo resultante: 0 — 100 — 200 — 600 ms. Para execução sequencial, use playSequentially.

Perguntas Frequentes

Como o Animator difere do ValueAnimator no Android?

Animator é uma classe base abstrata para todas as animações. ValueAnimator é sua subclasse que anima valores numéricos sem vincular a um objeto. ObjectAnimator (subclasse de ValueAnimator) anima uma propriedade específica de um objeto (por exemplo, alpha ou translationY). Para linha do tempo, use ValueAnimator como um temporizador universal com um callback via addUpdateListener.

Como sincronizar animações em diferentes dispositivos?

Use relógios do sistema (CACurrentMediaTime no iOS, System.nanoTime no Android) para calcular o progresso, não a contagem de quadros. Para sincronização em rede, use um temporizador baseado em NTP com correção de offset. O iOS suporta AVAudioSession para sincronização de linha do tempo de áudio-vídeo com precisão de milissegundos. Evite sincronização baseada em quadros — as taxas de quadros variam de 30 a 120 fps.

O que são startOffset e repeatCount no Animator?

startOffset é o atraso antes do início da animação em milissegundos. Usado para efeitos de cascata e escalonamento. repeatCount é o número de repetições: 0 = sem repetição, ValueAnimator.INFINITE = loop infinito. repeatMode determina a direção: RESTART (reiniciar do início) ou REVERSE (direção reversa). No iOS, startOffset é chamado beginTime (em combinação com CACurrentMediaTime), repeatCount é a mesma propriedade de CABasicAnimation.

Qual é a duração ideal da animação?

Material Design recomenda 200–350 ms para animações de interface. Animações com menos de 100 ms não são percebidas como animações, enquanto as com mais de 500 ms são irritantes. Para entrada/saída de elementos: 200–300 ms. Para transições entre telas: 300–400 ms. Use durações mais curtas para elementos pequenos (100–200 ms) e mais longas para elementos grandes (400–500 ms).

Por que a animação trepida durante a reprodução?

A trepidação (jank) ocorre devido a: operações de longa duração na thread principal (bloqueiam a renderização), hierarquia complexa de View/Layer com overdraw, ou uso incorreto da linha do tempo (duração não múltipla de vsync — 16ms para 60fps, 8ms para 120fps). Use Xcode Instruments Animations ou Android Studio Profiler para detectar quadros perdidos. No Compose, use Modifier.drawWithCache para armazenar em cache desenhos complexos.

Resumo

  • Timeline é um modelo de tempo de animação com parâmetros duration, startDelay, repeatCount, repeatMode que definem o fluxo da animação.
  • O protocolo iOS CAMediaTiming gerencia a linha do tempo através de duration, beginTime, speed, timeOffset, repeatCount, fillMode.
  • Android Animator e ValueAnimator fornecem duration, startDelay, repeatCount, repeatMode e setCurrentPlayTime para controle direto.
  • AnimatorSet no Android e CAAnimationGroup no iOS permitem combinar animações em uma única linha do tempo.
  • TimelineView no SwiftUI (iOS 15+) fornece acesso ao scheduler do sistema para linhas do tempo personalizadas sem a API Animation.
  • CACurrentMediaTime() no iOS e System.nanoTime no Android são carimbos de tempo base para sincronização de animações.
  • A duração ideal para animações de interface é de 200-350 ms de acordo com as recomendações do Material Design e HIG.

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