Зачем нужны анимации
Движение, которое направляет пользователей и радует их
«Зачем нужны анимации» — бесплатный урок Android Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 4 уроков всего.
Осмысленная анимация
Анимации — это не просто украшение. В отличном приложении Android движение направляет внимание, объясняет изменения и делает интерфейс отзывчивым и живым.
В этом курсе Вы изучите API анимации Jetpack Compose: от однострочных помощников animate*AsState до AnimatedVisibility, переходов и пружин на основе физических моделей.
Первый урок посвящён тому, зачем и когда использовать анимацию, чтобы каждое движение выполняло определённую задачу.
Compose анимирует декларативно
В Compose не нужно вручную запускать и останавливать анимации покадрово. Вместо этого Вы задаёте целевое значение, а Compose плавно движется к нему всякий раз, когда это значение изменяется.
Здесь цвет блока определяется одним логическим состоянием. Нажатие меняет состояние, и цвет автоматически плавно изменяется.
@Composable
fun ColorBox() {
var selected by remember { mutableStateOf(false) }
val color by animateColorAsState(
targetValue = if (selected) Color.Green else Color.Gray,
label = "box-color"
)
Box(
Modifier
.size(120.dp)
.background(color)
.clickable { selected = !selected }
)
}Отклик на действия пользователя
Одна из важнейших задач анимации — обратная связь. Когда пользователь нажимает кнопку или переключает элемент, небольшая анимация подтверждает, что приложение получило действие.
Мгновенные резкие изменения выглядят как сбой, а короткий переход длительностью 150–300 мс делает интерфейс более качественным. Здесь кнопка слегка уменьшается при нажатии.
@Composable
fun PressableButton(onClick: () -> Unit) {
var pressed by remember { mutableStateOf(false) }
val scale by animateFloatAsState(
targetValue = if (pressed) 0.92f else 1f,
label = "press-scale"
)
Button(
onClick = onClick,
modifier = Modifier.graphicsLayer {
scaleX = scale; scaleY = scale
}
) { Text("Tap me") }
}Объяснение изменений состояния
Когда интерфейс изменяется, анимация помогает пользователю понять, что только что произошло. Элемент, который плавно появляется и выезжает, воспринимается как «новый», а исчезающий — как «удалённый».
Без движения содержимое может резко появляться или исчезать, и пользователь не понимает, появилось ли что-то, исчезло или переместилось.
@Composable
fun Banner(visible: Boolean) {
AnimatedVisibility(
visible = visible,
enter = fadeIn() + slideInVertically(),
exit = fadeOut() + slideOutVertically()
) {
Text("Saved successfully!")
}
}Непрерывность и ощущение пространства
Движение сохраняет непрерывность. Когда карточка разворачивается или элемент перемещается в новую позицию, анимация изменения помогает пользователю ориентироваться в пространстве.
Compose может автоматически анимировать изменения компоновки с помощью Modifier.animateContentSize(), поэтому блок плавно увеличивается или уменьшается при изменении его содержимого.
@Composable
fun ExpandableCard(expanded: Boolean) {
Column(
Modifier
.fillMaxWidth()
.animateContentSize()
.padding(16.dp)
) {
Text("Title", style = MaterialTheme.typography.titleMedium)
if (expanded) {
Text("Here is the longer body that appears when expanded.")
}
}
}Важны длительность и темп
Хорошая анимация должна быть быстрой. Большинство переходов интерфейса должны длиться примерно от 150 до 400 мс. При слишком медленной анимации приложение кажется неповоротливым, а при слишком быстрой движение становится незаметным.
Compose позволяет настраивать длительность и темп с помощью tween и кривой easing. Сглаживание делает движение естественным, ускоряя и замедляя его.
val offset by animateDpAsState(
targetValue = if (open) 0.dp else 200.dp,
animationSpec = tween(
durationMillis = 300,
easing = FastOutSlowInEasing
),
label = "panel-offset"
)Не переусердствуйте
Анимация — мощный инструмент, поэтому её легко использовать чрезмерно. Слишком много движения отвлекает, замедляет работу и даже может вызывать дискомфорт.
Несколько простых правил:
- Используйте анимацию для передачи смысла, а не для украшения.
- Делайте переходы короткими и ненавязчивыми.
- Не анимируйте одновременно всё содержимое экрана.
- Никогда не мешайте пользователю выполнять действия во время анимации.
Учитывайте доступность
Некоторые пользователи включают параметр Удалить анимации в системных настройках из-за повышенной чувствительности к движению. Внимательное приложение учитывает это предпочтение.
Можно узнать, установлен ли масштаб анимаций равным нулю, и соответственно уменьшить или отключить необязательные движения.
@Composable
fun rememberReduceMotion(): Boolean {
val context = LocalContext.current
val scale = Settings.Global.getFloat(
context.contentResolver,
Settings.Global.ANIMATOR_DURATION_SCALE,
1f
)
return scale == 0f
}Набор инструментов анимации Compose
Compose предлагает многоуровневый набор API для анимации. В этом курсе Вы познакомитесь с ними:
animate*AsState— анимация одного значения (цвета, размера, числа с плавающей точкой).AnimatedVisibility— анимация появления и исчезновения.updateTransition— согласованная анимация нескольких значений.AnimatedContent— плавное смешивание разных элементов содержимого.Animatableиspring— низкоуровневое управление на основе физики.
Начинайте с высокоуровневых API и переходите на более низкий уровень только при необходимости более точного контроля.
Анимация следует за состоянием
Ментальная модель, которая помогает понять всё остальное: в Compose анимации отслеживают состояние. Вы изменяете значение, а API анимации плавно приближает интерфейс к новому значению на каждом кадре.
Это означает, что Вам редко приходится описывать временную шкалу. Вы объявляете: «это свойство должно быть равно X», а Compose сам обрабатывает промежуточные кадры.
@Composable
fun FadingText(highlighted: Boolean) {
val alpha by animateFloatAsState(
targetValue = if (highlighted) 1f else 0.4f,
label = "text-alpha"
)
Text(
"Status",
modifier = Modifier.graphicsLayer { this.alpha = alpha }
)
}Краткая разминка на чистом Kotlin
Анимации интерполируют значения. В основе лежит простая математика: дробь t от 0 до 1 смешивает начальное и конечное значения. Эта идея — линейная интерполяция, или lerp, — лежит в основе каждой создаваемой Вами анимации.
Этот небольшой фрагмент на чистом Kotlin показывает принцип, который Compose применяет много раз в секунду.
fun lerp(start: Float, end: Float, t: Float): Float =
start + (end - start) * t
fun main() {
for (i in 0..4) {
val t = i / 4f
println("t=$t -> ${lerp(0f, 100f, t)}")
}
}Быстрая проверка
Какова основная ментальная модель анимаций в Jetpack Compose?
Итоги: осмысленное движение
Теперь Вы знаете, почему анимация важна и какая модель лежит в её основе:
- Движение даёт обратную связь, объясняет изменения и сохраняет непрерывность.
- Анимации Compose являются декларативными и следуют за состоянием.
- Переходы должны быть короткими (примерно 150–400 мс) и оправданными; не используйте анимацию чрезмерно.
- Учитывайте потребности пользователей, которые уменьшают количество движения для повышения доступности.
- Сначала обращайтесь к высокоуровневым API:
animate*AsState,AnimatedVisibility, переходам и пружинам.
Далее: анимация отдельных значений с помощью семейства animate*AsState.
Часто задаваемые вопросы
Урок «Зачем нужны анимации» бесплатный?
Да — полный текст урока «Зачем нужны анимации» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 4 уроков всего.
Чему я научусь в уроке «Зачем нужны анимации»?
Движение, которое направляет пользователей и радует их Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Android Academy?
Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Зачем нужны анимации»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Android Academy?
Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Зачем нужны анимации
- Основы animate*AsState
- AnimatedVisibility и переходы
- Анимации жестов и пружин