Timeline — dasar, pengelolaan waktu animasi di aplikasi

Penulis: IT Sectr Diterbitkan: 2026-03-02 Waktu membaca: 8 mnt
Timeline (garis waktu) — konsep fundamental animasi yang menentukan berapa lama animasi berlangsung, dalam urutan apa tahapannya dijalankan, dan bagaimana waktu dipetakan ke kemajuan. Dalam pengembangan aplikasi seluler, timeline dikelola melalui durasi (duration), penundaan (delay), pengulangan (repeat), dan stempel waktu. Di iOS, timeline animasi diimplementasikan melalui CACurrentMediaTime dan CAMediaTiming, di Android — melalui ValueAnimator dan Animator dengan parameter duration, startDelay, dan repeatCount. Menurut Dokumentasi Apple, pengelolaan garis waktu yang tepat sangat penting untuk sinkronisasi animasi: desinkronisasi bahkan 16 ms (satu frame pada 60fps) dirasakan oleh pengguna sebagai kegagapan. Di IT Sectr kami telah menstandarisasi penggunaan timeline melalui ValueAnimator di Android dan CABasicAnimation dengan CAMediaTiming di iOS — ini memastikan pengelolaan waktu yang seragam di semua proyek.

Poin Utama

  • Timeline — konsep pengelolaan waktu animasi: duration, delay, repeat, pemetaan waktu ke kemajuan.
  • CAMediaTiming — protokol iOS Core Animation untuk pengelolaan timeline: duration, beginTime, repeatCount, speed, timeOffset.
  • ValueAnimator — kelas sentral Android untuk bekerja dengan garis waktu animasi melalui duration, startDelay, repeatCount.
  • CACurrentMediaTime — fungsi iOS untuk mendapatkan waktu absolut dalam detik, digunakan untuk sinkronisasi.
  • TimeInterval — tipe data di iOS (Double) yang mewakili interval waktu untuk perhitungan animasi.

Apa itu Timeline?

Timeline — adalah model waktu animasi yang menentukan kapan animasi dimulai, berapa lama berlangsung, dan bagaimana perjalanan waktu diubah menjadi perubahan parameter yang dianimasikan. Tidak seperti animasi bingkai demi bingkai (frame-by-frame), di mana setiap bingkai diatur secara manual, animasi timeline dijelaskan dengan parameter: duration — durasi total, startDelay — penundaan sebelum mulai, repeatCount — jumlah pengulangan, dan timingFunction — kurva kecepatan.

Garis waktu bekerja dalam ruang yang dinormalisasi [0, 1] — local time atau progress. Nilai nol sesuai dengan awal animasi, satu — dengan akhir. Fungsi easing mengubah local time linier menjadi kemajuan animasi yang sebenarnya. Jika repeatCount > 1, timeline secara siklis di-reset (RESTART) atau dibalik (REVERSE). Di iOS, CAMediaTiming menambahkan parameter speed (kecepatan pemutaran, >1 mempercepat) dan timeOffset (pergeseran garis waktu). Di Android, Animator menggunakan setCurrentPlayTime() untuk pengelolaan posisi langsung pada garis waktu. Menurut Material Design, animasi yang lebih pendek dari 100 ms tidak dirasakan sebagai animasi, dan yang lebih panjang dari 500 ms — mulai mengganggu. Durasi optimal untuk animasi antarmuka adalah 200–350 ms.

Timeline di iOS: CAMediaTiming dan CACurrentMediaTime

Di iOS, pengelolaan garis waktu animasi dilakukan melalui protokol CAMediaTiming, yang diimplementasikan oleh CAAnimation dan CALayer. Ini menyediakan properti: duration (durasi dalam detik), beginTime (waktu mulai relatif terhadap timeline induk), repeatCount (jumlah pengulangan), repeatDuration (total durasi pengulangan), autoreverses (gerakan mundur otomatis), fillMode (perilaku sebelum/setelah animasi), speed (kecepatan pemutaran), dan timeOffset (pergeseran pada garis).

CACurrentMediaTime() — fungsi yang mengembalikan waktu absolut dalam detik sejak restart terakhir perangkat. Digunakan sebagai stempel waktu dasar untuk sinkronisasi beberapa animasi: atur beginTime = CACurrentMediaTime() + offset untuk memulai grup animasi dengan penundaan yang tepat. CAMediaTiming juga mendukung hierarki timeline — lapisan induk dapat mempercepat/memperlambat semua animasi anak melalui properti speed. Di UIKit, UIViewPropertyAnimator (iOS 10+) mengabstraksi garis waktu melalui properti duration, delay, dan callback startAnimation/pauseAnimation/stopAnimation. Di SwiftUI, struktur Animation menyediakan duration sebagai bagian dari spesifikasi animasi, tetapi pengelolaan langsung garis waktu tersembunyi — untuk timeline kustom gunakan TimelineView (iOS 15+) dengan scheduler sendiri.

Timeline di Android: Animator dan duration

Di Android, pengelolaan garis waktu terpusat di kelas Animator dan turunannya (ValueAnimator, ObjectAnimator). Properti utama timeline: duration (durasi dalam milidetik), startDelay (penundaan sebelum mulai), repeatCount (jumlah pengulangan), repeatMode (RESTART atau REVERSE). Metode setCurrentPlayTime(long) memungkinkan pergerakan ke posisi mana pun pada garis waktu.

ValueAnimator menambahkan tingkat abstraksi: menghasilkan nilai dari 0 hingga 1 (normalized time) berdasarkan duration dan meneruskannya ke TimeInterpolator. AnimatorSet memungkinkan penggabungan beberapa Animator menjadi satu garis waktu dengan eksekusi berurutan (playSequentially) atau paralel (playTogether). Di Jetpack Compose, garis waktu dikelola melalui AnimationSpec: tween (durationMillis, delayMillis, easing), spring (dampingRatio, stiffness), dan keyframes (titik pada garis waktu dengan easing kustom untuk setiap segmen). Compose AnimatedContent menggunakan timeline untuk transitionSpec — pengembang menjelaskan bagaimana konten muncul/hilang dengan pergeseran waktu. Menurut Android Performance, garis waktu animasi harus kelipatan 16 ms (siklus vsync) untuk 60fps — durasi yang salah dapat menyebabkan frame loss karena ketidakcocokan dengan refresh rate layar.

Komposisi animasi dalam waktu

Garis waktu menjadi sangat penting dalam komposisi beberapa animasi. Tiga pola dasar: kaskade — animasi dimulai secara berurutan dengan pergeseran (setiap berikutnya dimulai setelah offset dari sebelumnya), paralel — semua animasi dimulai secara bersamaan dengan timeline yang sama, dan stagger — animasi dimulai dengan tumpang tindih (yang kedua dimulai sebelum yang pertama selesai).

Di iOS, kaskade diimplementasikan melalui beginTime setiap CAAnimation = beginTime sebelumnya + duration sebelumnya. Untuk stagger, digunakan CAAnimationGroup dengan beginTime berbeda dalam animasi bersarang. Di Android, AnimatorSet mendukung playSequentially dan playTogether; stagger dibuat dengan mengatur startDelay untuk setiap Animator. Di Compose, AnimatedVisibility dengan enter/exitTransition menggunakan stagger dalam varian staggerChildren untuk kemunculan berjenjang elemen daftar. Di WWDC dan Google I/O 2024, kedua platform memperkenalkan alat visualisasi timeline: Xcode Animations Inspector dan Android Studio Animations Timeline — mereka menunjukkan garis waktu aktual dan frame yang terlewat secara real-time.

Contoh Kode

iOS: CABasicAnimation dengan CAMediaTiming

Contoh animasi dengan timeline kustom: penundaan 0,3 detik, durasi 0,6 detik, autoreverse, dan pengulangan tak terbatas. CAMediaTiming mengelola semua parameter waktu.

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 memberikan penundaan 300 ms. autoreverses = true menyebabkan animasi bergerak ke arah berlawanan setelah setiap siklus. repeatCount = .infinity menciptakan loop tak terbatas dari efek “bernafas”. speed = 1,0 — kecepatan normal; percepat animasi 2 kali dengan nilai 2,0.

iOS: TimelineView untuk garis waktu kustom

SwiftUI TimelineView (iOS 15+) menyediakan akses ke timeline sistem untuk animasi kustom. Tampilan diperbarui pada setiap tick 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 dengan scheduler .periodic menghasilkan tick setiap 0,1 detik. Dalam closure, context.date — waktu saat ini yang diubah menjadi fase sinusoida. Ukuran lingkaran berdenyut dengan frekuensi 1 Hz. TimelineView adalah satu-satunya cara untuk membuat animasi dengan garis waktu sendiri di SwiftUI tanpa Animation API.

Android: ValueAnimator dengan timeline kustom

ValueAnimator dengan pengelolaan garis waktu penuh: penundaan, durasi, pengulangan. Metode setCurrentPlayTime memungkinkan melompat pada garis waktu.

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 — penundaan sebelum mulai. repeatMode = REVERSE mengembalikan animasi ke nilai awal. animatedFraction memberikan kemajuan dari 0 hingga 1 dengan mempertimbangkan repeatMode. addUpdateListener dipanggil setiap frame (biasanya 16 ms). Untuk menjeda, gunakan pause() / resume().

Android: AnimatorSet untuk komposisi timeline

AnimatorSet memungkinkan pembuatan garis waktu kompleks dari beberapa animasi. Dalam contoh — eksekusi berurutan dengan tumpang tindih (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 memulai semua animasi secara paralel, tetapi setiap animasi memiliki startDelay sendiri — ini menciptakan efek stagger: fadeIn mulai pertama (0 ms), slideUp setelah 100 ms, scale setelah 200 ms. Garis waktu yang dihasilkan: 0 — 100 — 200 — 600 ms. Untuk eksekusi berurutan, gunakan playSequentially.

Pertanyaan Umum

Apa perbedaan Animator dan ValueAnimator di Android?

Animator — kelas dasar abstrak untuk semua animasi. ValueAnimator — subkelasnya yang menganimasi nilai numerik tanpa terikat ke objek. ObjectAnimator (pewaris ValueAnimator) menganimasi properti spesifik objek (misalnya, alpha atau translationY). Untuk timeline, gunakan ValueAnimator sebagai timer universal dengan callback melalui addUpdateListener.

Bagaimana cara menyinkronkan animasi di perangkat berbeda?

Gunakan jam sistem (CACurrentMediaTime di iOS, System.nanoTime di Android) untuk menghitung kemajuan, bukan jumlah frame. Untuk sinkronisasi jaringan, gunakan timer berbasis NTP dengan koreksi offset. iOS mendukung AVAudioSession untuk sinkronisasi timeline audio-video dengan akurasi milidetik. Hindari sinkronisasi berdasarkan frame — frame rate bervariasi dari 30 hingga 120 fps.

Apa itu startOffset dan repeatCount di Animator?

startOffset — penundaan sebelum memulai animasi dalam milidetik. Digunakan untuk efek kaskade dan stagger. repeatCount — jumlah pengulangan: 0 = tidak diulang, ValueAnimator.INFINITE = loop tak terbatas. repeatMode menentukan arah: RESTART (reset ke awal) atau REVERSE (gerakan mundur). Di iOS, startOffset disebut beginTime (dalam kombinasi dengan CACurrentMediaTime), repeatCount — properti dengan nama yang sama di CABasicAnimation.

Berapa durasi optimal animasi?

Material Design merekomendasikan 200–350 ms untuk animasi antarmuka. Animasi lebih pendek dari 100 ms tidak dirasakan sebagai animasi, lebih panjang dari 500 ms — mengganggu. Untuk masuk/keluar elemen: 200–300 ms. Untuk transisi antar layar: 300–400 ms. Gunakan durasi lebih pendek untuk elemen kecil (100–200 ms) dan lebih panjang untuk elemen besar (400–500 ms).

Mengapa animasi tersendat saat diputar?

Tersendat (jank) terjadi karena: operasi lama di thread utama (memblokir rendering), hierarki View/Layer kompleks dengan overdraw, atau penggunaan timeline yang salah (durasi bukan kelipatan vsync — 16ms untuk 60fps, 8ms untuk 120fps). Gunakan Xcode Instruments Animations atau Android Studio Profiler untuk mendeteksi frame yang terlewat. Di Compose, gunakan Modifier.drawWithCache untuk caching gambar kompleks.

Ringkasan

  • Timeline — model waktu animasi dengan parameter duration, startDelay, repeatCount, repeatMode, yang menentukan jalannya animasi.
  • Protokol iOS CAMediaTiming mengelola garis waktu melalui duration, beginTime, speed, timeOffset, repeatCount, fillMode.
  • Android Animator dan ValueAnimator menyediakan duration, startDelay, repeatCount, repeatMode, dan setCurrentPlayTime untuk pengelolaan langsung.
  • AnimatorSet di Android dan CAAnimationGroup di iOS memungkinkan penggabungan animasi dalam satu garis waktu.
  • TimelineView di SwiftUI (iOS 15+) menyediakan akses ke scheduler sistem untuk garis waktu kustom tanpa Animation API.
  • CACurrentMediaTime() di iOS dan System.nanoTime di Android — stempel waktu dasar untuk sinkronisasi animasi.
  • Durasi optimal animasi antarmuka — 200-350 ms sesuai rekomendasi Material Design dan HIG.

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga