Как анимировать переход между двумя экранами
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Анимация перехода между экранами в 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>
Рекомендации и лучшие практики
-
Оптимизация производительности: Избегайте анимаций на главном потоке, которые могут вызвать пропуск кадров. Для сложных анимаций используйте
ValueAnimatorилиObjectAnimatorс аппаратным ускорением. -
Согласованность стиля: Все анимации в приложении должны следовать единому стилю и длительности (обычно 300-500 мс).
-
Обратная совместимость: Проверяйте работу анимаций на старых версиях Android. Для API < 21 используйте fallback-решения или библиотеки типа TransitionsEverywhere.
-
Доступность: Учитывайте настройки доступности — если пользователь отключил анимации в системе, ваше приложение должно это учитывать:
if (Settings.Global.getFloat(
contentResolver,
Settings.Global.ANIMATOR_DURATION_SCALE, 1f) == 0f) {
// Анимации отключены в системе
}
- Тестирование: Всегда тестируйте анимации на реальных устройствах разной производительности и в разных сценариях (поворот экрана, переход в бэкстек).
Пример комплексного решения
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()
}
}
Правильно реализованные анимации переходов не только улучшают пользовательский опыт, но и помогают пользователю понять навигационную иерархию приложения, создавая визуальные связи между связанными экранами. Ключевой принцип — умеренность: анимации должны быть ненавязчивыми и выполнять функциональную роль, а не просто быть декоративным элементом.