Lottie Android для Kotlin: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Lottie Android для Kotlin: полное руководство с примерами

1. Что это и зачем нужна

Lottie — это библиотека с открытым исходным кодом от Airbnb, которая позволяет рендерить анимации After Effects в реальном времени на мобильных устройствах и в вебе. Для Android существует официальная библиотека com.airbnb.android:lottie, которая полностью поддерживает язык Kotlin. Анимации экспортируются из After Effects в формат JSON (через плагин Bodymovin) и затем воспроизводятся в приложении без потери качества и с минимальным размером файла.

Зачем нужна Lottie? Во-первых, она кардинально упрощает работу дизайнеров и разработчиков: дизайнер создаёт сложную анимацию в привычном инструменте, а разработчик просто подключает JSON-файл. Во-вторых, Lottie обеспечивает высокую производительность — анимации рендерятся на GPU, что даёт 60 FPS даже на старых устройствах. В-третьих, библиотека поддерживает интерактивность: можно управлять воспроизведением, менять скорость, цвета, размеры и даже программно анимировать отдельные слои.

Lottie Android идеально подходит для: загрузочных экранов (сплешей), анимированных иконок, переходов между экранами, реакций на жесты пользователя, микроанимаций в UI и многого другого. Библиотека активно поддерживается сообществом и имеет тысячи готовых бесплатных анимаций на LottieFiles.

2. Установка

Для установки Lottie в проект Android на Kotlin необходимо добавить зависимость в файл build.gradle (уровня модуля):

dependencies {
    implementation 'com.airbnb.android:lottie:6.4.0'
}

Если вы используете Kotlin DSL (build.gradle.kts):

dependencies {
    implementation("com.airbnb.android:lottie:6.4.0")
}

После синхронизации Gradle библиотека готова к использованию. Минимальная версия Android SDK — 21 (Android 5.0).

Обратите внимание: команды pip, npm или cargo для этой библиотеки не используются, так как это нативная Android-библиотека.

3. Быстрый старт — минимальный рабочий пример

Поместите JSON-файл анимации (например, animation.json) в папку app/src/main/res/raw. Затем добавьте LottieAnimationView в ваш layout-файл:

<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.airbnb.lottie.LottieAnimationView
        android:id="@+id/animationView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        app:lottie_rawRes="@raw/animation"
        app:lottie_autoPlay="true"
        app:lottie_loop="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Код в Activity (или Fragment) на Kotlin:

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.airbnb.lottie.LottieAnimationView

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val animationView: LottieAnimationView = findViewById(R.id.animationView)
        animationView.playAnimation()
    }
}

Этот минимальный пример воспроизведёт анимацию из ресурса raw/animation.json в бесконечном цикле.

4. Основные методы/функции/классы

4.1 playAnimation()

Сигнатура: fun playAnimation()

Что делает: Запускает воспроизведение анимации с текущей позиции. Если анимация уже завершена, начинает сначала.

animationView.playAnimation()

4.2 pauseAnimation()

Сигнатура: fun pauseAnimation()

Что делает: Приостанавливает воспроизведение на текущем кадре.

animationView.pauseAnimation()

4.3 cancelAnimation()

Сигнатура: fun cancelAnimation()

Что делает: Останавливает анимацию и сбрасывает позицию на начало.

animationView.cancelAnimation()

4.4 setSpeed(float speed)

Сигнатура: fun setSpeed(speed: Float)

Что делает: Устанавливает скорость воспроизведения. Значение 1.0 — нормальная скорость, 2.0 — вдвое быстрее, 0.5 — вдвое медленнее. Отрицательные значения запускают анимацию в обратном направлении.

animationView.setSpeed(2.0f) // Ускоренная анимация
animationView.setSpeed(-1.0f) // Обратное воспроизведение

4.5 setProgress(float progress)

Сигнатура: fun setProgress(progress: Float)

Что делает: Устанавливает анимацию на определённый кадр, где progress — значение от 0.0 (начало) до 1.0 (конец). Полезно для создания интерактивных анимаций, привязанных к скроллу или жестам.

animationView.setProgress(0.5f) // Переход на середину анимации

4.6 addAnimatorListener(Animator.AnimatorListener)

Сигнатура: fun addAnimatorListener(listener: Animator.AnimatorListener)

Что делает: Добавляет слушатель событий анимации: начало, конец, отмена, повтор.

animationView.addAnimatorListener(object : Animator.AnimatorListener {
    override fun onAnimationStart(animation: Animator) {
        Log.d("Lottie", "Анимация началась")
    }

    override fun onAnimationEnd(animation: Animator) {
        Log.d("Lottie", "Анимация завершилась")
    }

    override fun onAnimationCancel(animation: Animator) {
        Log.d("Lottie", "Анимация отменена")
    }

    override fun onAnimationRepeat(animation: Animator) {
        Log.d("Lottie", "Анимация повторяется")
    }
})

4.7 setAnimation(String animationName)

Сигнатура: fun setAnimation(animationName: String)

Что делает: Загружает анимацию из папки assets по имени файла (без расширения). Альтернатива lottie_rawRes в XML.

animationView.setAnimation("loading_spinner.json")
animationView.playAnimation()

4.8 setAnimationFromUrl(String url)

Сигнатура: fun setAnimationFromUrl(url: String)

Что делает: Загружает анимацию по URL-адресу. Асинхронно скачивает JSON и начинает воспроизведение. Требует разрешения INTERNET в манифесте.

animationView.setAnimationFromUrl("https://assets2.lottiefiles.com/packages/lf20_UJNc2t.json")
animationView.playAnimation()

4.9 setRepeatCount(int count)

Сигнатура: fun setRepeatCount(count: Int)

Что делает: Устанавливает количество повторений анимации. Значение LottieDrawable.INFINITE (или -1) — бесконечный повтор.

animationView.setRepeatCount(3) // Повторить 3 раза
animationView.setRepeatCount(LottieDrawable.INFINITE) // Бесконечно

4.10 useHardwareAcceleration(boolean use)

Сигнатура: fun useHardwareAcceleration(use: Boolean)

Что делает: Включает или отключает аппаратное ускорение для рендеринга. По умолчанию включено. Отключайте, если наблюдаются графические артефакты.

animationView.useHardwareAcceleration(false)

5. Реальный практический пример (100-200 строк кода)

Создадим экран профиля пользователя с анимированной аватаркой. Анимация будет реагировать на нажатие: при клике — проигрываться, а при долгом нажатии — менять цвет.

// ProfileActivity.kt
import android.animation.Animator
import android.graphics.ColorFilter
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.os.Bundle
import android.view.MotionEvent
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieProperty
import com.airbnb.lottie.model.KeyPath
import com.airbnb.lottie.value.LottieFrameInfo
import com.airbnb.lottie.value.SimpleLottieValueCallback

class ProfileActivity : AppCompatActivity() {

    private lateinit var avatarView: LottieAnimationView
    private lateinit var statusText: TextView
    private lateinit var resetButton: Button
    private var isAnimating = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_profile)

        avatarView = findViewById(R.id.avatarView)
        statusText = findViewById(R.id.statusText)
        resetButton = findViewById(R.id.resetButton)

        // Настройка анимации
        avatarView.setAnimation("profile_avatar.json")
        avatarView.setRepeatCount(0) // Один раз
        avatarView.setSpeed(1.5f)

        // Слушатель событий
        avatarView.addAnimatorListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator) {
                isAnimating = true
                statusText.text = "Анимация запущена"
            }

            override fun onAnimationEnd(animation: Animator) {
                isAnimating = false
                statusText.text = "Анимация завершена"
                Toast.makeText(this@ProfileActivity, "Привет!", Toast.LENGTH_SHORT).show()
            }

            override fun onAnimationCancel(animation: Animator) {
                isAnimating = false
                statusText.text = "Анимация отменена"
            }

            override fun onAnimationRepeat(animation: Animator) {
                // Не используется
            }
        })

        // Обработка нажатия
        avatarView.setOnClickListener {
            if (!isAnimating) {
                avatarView.playAnimation()
            }
        }

        // Долгое нажатие — меняем цвет
        avatarView.setOnLongClickListener {
            changeAvatarColor()
            true
        }

        // Кнопка сброса
        resetButton.setOnClickListener {
            avatarView.cancelAnimation()
            avatarView.setProgress(0f)
            resetAvatarColor()
            statusText.text = "Сброшено"
        }
    }

    private fun changeAvatarColor() {
        // Меняем цвет всех слоёв с именем "**" (все слои)
        avatarView.addValueCallback(
            KeyPath("**"),
            LottieProperty.COLOR_FILTER
        ) { frameInfo: LottieFrameInfo ->
            PorterDuffColorFilter(
                resources.getColor(R.color.purple_500, theme),
                PorterDuff.Mode.SRC_ATOP
            )
        }
        statusText.text = "Цвет изменён"
    }

    private fun resetAvatarColor() {
        avatarView.addValueCallback(
            KeyPath("**"),
            LottieProperty.COLOR_FILTER
        ) { null } // Убираем фильтр
        statusText.text = "Цвет сброшен"
    }
}
<!-- activity_profile.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="24dp">

    <com.airbnb.lottie.LottieAnimationView
        android:id="@+id/avatarView"
        android:layout_width="150dp"
        android:layout_height="150dp"
        app:lottie_rawRes="@raw/profile_avatar"
        app:lottie_autoPlay="false"
        app:lottie_loop="false" />

    <TextView
        android:id="@+id/statusText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Нажми на аватар"
        android:textSize="16sp" />

    <Button
        android:id="@+id/resetButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Сбросить" />

</LinearLayout>

6. Советы по производительности и типичные ошибки

Советы по производительности

  • Используйте аппаратное ускорение — оно включено по умолчанию и значительно повышает FPS. Отключайте только при артефактах.
  • Оптимизируйте JSON-файлы — удаляйте неиспользуемые слои в After Effects перед экспортом. Исп

Рекомендаций