Анимации: обзор

Обзорно знакомимся с анимациями Compose: плавное изменение значений и появление/исчезновение элементов.

Анимация в Compose — это состояние, которое меняется не скачком, а плавно во времени; UI перерисовывается на каждом кадре перехода.

Анимация значения: animate*AsState

Простейший способ — функции вида animateColorAsState, animateDpAsState и т.п. Вы задаёте целевое значение, а Compose плавно ведёт к нему текущее:

@Composable
fun ExpandBox(expanded: Boolean) {
    val size by animateDpAsState(targetValue = if (expanded) 200.dp else 100.dp)
    Box(modifier = Modifier.size(size).background(Color.Blue))
}

Когда expanded меняется, целевой размер меняется скачком, но size плавно перетекает от старого к новому за несколько кадров. Каждый кадр — это recomposition с новым промежуточным значением.

Появление и исчезновение: AnimatedVisibility

AnimatedVisibility анимирует вход и выход элемента из дерева:

@Composable
fun Hint(visible: Boolean) {
    AnimatedVisibility(visible = visible) {
        Text("Подсказка появляется плавно")
    }
}

По умолчанию элемент появляется с fade и расширением, а исчезает обратно. Поведение настраивается параметрами enter и exit: например, fadeIn() + slideInVertically() заставит элемент проявляться и выезжать снизу. Важно, что AnimatedVisibility не просто меняет прозрачность — он удерживает элемент в дереве на время анимации ухода, чтобы тот успел плавно исчезнуть, и лишь потом убирает его.

Виды анимаций (обзор)

ИнструментДля чего
animateDpAsState и аналогиплавное изменение одного значения
AnimatedVisibilityпоявление/исчезновение элемента
Crossfadeплавная замена одного контента другим
updateTransitionсогласованная анимация нескольких свойств

Как работает под капотом

Анимация — это просто специальное состояние, меняющееся со временем. animateDpAsState заводит внутренний таймер: на каждом кадре он вычисляет промежуточное значение по кривой (например, плавный разгон и торможение) и обновляет состояние. Обновление состояния вызывает recomposition — так картинка перерисовывается 60 и более раз в секунду, создавая иллюзию движения. Никакой отдельной «системы анимаций» поверх UI нет: всё построено на том же механизме состояния и recomposition.

Частые ошибки

  • Анимировать слишком много свойств по отдельности вместо updateTransition — рассинхрон и лишние перерисовки.
  • Запускать тяжёлые вычисления на каждом кадре анимации — заметные подтормаживания.
  • Ждать, что анимация сработает без изменения целевого значения — она реагирует именно на смену цели.

Итог

  • Анимация в Compose — это плавно меняющееся со временем состояние.
  • animate*AsState плавно ведёт значение к новой цели.
  • AnimatedVisibility анимирует появление и исчезновение элементов.
Проверьте себя
1. Как Compose реализует анимацию по своей сути?
AЧерез отдельную систему поверх UI
BЧерез плавно меняющееся со временем состояние, которое вызывает recomposition каждый кадр
CЧерез предзаписанные видеофайлы
DЧерез изменение XML на лету
2. Что делает animateDpAsState?
AМеняет размер мгновенно
BПлавно ведёт значение Dp от текущего к целевому за несколько кадров
CЗапускает корутину при клике
DАнимирует только цвет