← Назад к вопросам

Как анимировать переход между двумя экранами

2.0 Middle🔥 141 комментариев
#UI и вёрстка#Жизненный цикл и навигация

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Анимация перехода между экранами в Android

Анимация переходов между экранами — важная часть UX, которая делает навигацию плавной и визуально приятной. В Android существует несколько подходов для реализации таких анимаций, каждый со своими сценариями применения.

Основные подходы

1. Анимации через ресурсы (XML)

Самый простой способ — определить анимации в XML-файлах в папке res/anim/ и использовать их при старте активности или в фрагментах.

Пример анимаций в XML:

<!-- res/anim/slide_in_right.xml -->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:fromXDelta="100%"
        android:toXDelta="0%" />
</set>

<!-- res/anim/slide_out_left.xml -->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:fromXDelta="0%"
        android:toXDelta="-100%" />
</set>

Использование при запуске Activity:

val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left)

Для фрагментов:

supportFragmentManager.beginTransaction()
    .setCustomAnimations(
        R.anim.slide_in_right,
        R.anim.slide_out_left,
        R.anim.slide_in_left,
        R.anim.slide_out_right
    )
    .replace(R.id.container, SecondFragment())
    .addToBackStack(null)
    .commit()

2. Shared Element Transition (совместные элементы)

Современный подход, позволяющий анимировать общие элементы между экранами (например, изображения, заголовки). Требует Android 5.0+ (API 21).

Настройка в разметке:

<!-- В первом элементе указываем transitionName -->
<ImageView
    android:id="@+id/avatar"
    android:transitionName="avatar_transition"
    android:src="@drawable/avatar" />

<!-- Во втором элементе (на следующем экране) указываем такой же transitionName -->
<ImageView
    android:id="@+id/avatar_detail"
    android:transitionName="avatar_transition"
    android:src="@drawable/avatar" />

Код для запуска:

// В первой Activity/Fragment
val intent = Intent(this, DetailActivity::class.java)
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(
    this,
    avatarView, // исходный View
    "avatar_transition" // transitionName
)
startActivity(intent, options.toBundle())

3. Программные анимации через MotionLayout

Более сложные, но мощные анимации можно создать с помощью MotionLayout (часть Jetpack ConstraintLayout 2.0+).

Пример структуры MotionScene:

<!-- res/xml/scene_transition.xml -->
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">
    
    <Transition
        motion:constraintSetStart="@id/start"
        motion:constraintSetEnd="@id/end"
        motion:duration="500">
        
        <OnClick motion:targetId="@id/button"
                motion:clickAction="toggle" />
    </Transition>
    
    <ConstraintSet android:id="@+id/start">
        <Constraint android:id="@+id/avatar"
            android:layout_width="64dp"
            android:layout_height="64dp"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>
    
    <ConstraintSet android:id="@+id/end">
        <Constraint android:id="@+id/avatar"
            android:layout_width="200dp"
            android:layout_height="200dp"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>
</MotionScene>

Рекомендации и лучшие практики

  1. Оптимизация производительности: Избегайте анимаций на главном потоке, которые могут вызвать пропуск кадров. Для сложных анимаций используйте ValueAnimator или ObjectAnimator с аппаратным ускорением.

  2. Согласованность стиля: Все анимации в приложении должны следовать единому стилю и длительности (обычно 300-500 мс).

  3. Обратная совместимость: Проверяйте работу анимаций на старых версиях Android. Для API < 21 используйте fallback-решения или библиотеки типа TransitionsEverywhere.

  4. Доступность: Учитывайте настройки доступности — если пользователь отключил анимации в системе, ваше приложение должно это учитывать:

if (Settings.Global.getFloat(
    contentResolver,
    Settings.Global.ANIMATOR_DURATION_SCALE, 1f) == 0f) {
    // Анимации отключены в системе
}
  1. Тестирование: Всегда тестируйте анимации на реальных устройствах разной производительности и в разных сценариях (поворот экрана, переход в бэкстек).

Пример комплексного решения

class AnimatedNavigationActivity : AppCompatActivity() {
    
    fun navigateWithTransition(destination: Fragment, sharedView: View) {
        val transitionName = "shared_element_${sharedView.id}"
        ViewCompat.setTransitionName(sharedView, transitionName)
        
        val fragment = destination.apply {
            sharedElementEnterTransition = MaterialContainerTransform().apply {
                duration = 300L
                fadeMode = MaterialContainerTransform.FADE_MODE_IN
            }
        }
        
        supportFragmentManager.beginTransaction()
            .setReorderingAllowed(true)
            .addSharedElement(sharedView, transitionName)
            .replace(R.id.container, fragment)
            .addToBackStack(null)
            .commit()
    }
}

Правильно реализованные анимации переходов не только улучшают пользовательский опыт, но и помогают пользователю понять навигационную иерархию приложения, создавая визуальные связи между связанными экранами. Ключевой принцип — умеренность: анимации должны быть ненавязчивыми и выполнять функциональную роль, а не просто быть декоративным элементом.