Когда к компоненту AnimatedVisibility применяются анимации, они применяются ко всем вложенным компонентам. Однако специальная функция-модификатор animateEnterExit() позволяет определить анимацию на уровне отдельных компонентов. Как и в случае с AnimatedVisibility, этот модификатор позволяет объявлять анимацию появления и исчезновения компонента на экране. Но важно отметить, что этот модификатор применяется не сам по себе в любом месте пользовательского интерфейса, а только в рамках AnimatedVisibility.
Модификатор animateEnterExit() имеет следующее определение:
@ExperimentalAnimationApi public open fun Modifier.animateEnterExit( enter: EnterTransition = fadeIn() + expandIn(), exit: ExitTransition = fadeOut() + shrinkOut(), label: String = "animateEnterExit" ): Modifier
Как и AnimatedVisibility, модификатор использует параметры enter
и exit
для определения анимации появления и исчезновения компонента на экране. Кроме того с помощью параметра
label
можно назначить текстовую метку. Поскольку данный модификатор является экспериментальным то при его использовании к компоненту следует применять аннотацию @ExperimentalAnimationApi
Пример применения модификатора animateEnterExit:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.tween import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent @ExperimentalAnimationApi{ val boxVisible = remember { mutableStateOf(true) } Column(Modifier.padding(20.dp), horizontalAlignment = Alignment.CenterHorizontally) { AnimatedVisibility( visible = boxVisible.value, Modifier.padding(40.dp), enter = EnterTransition.None, exit = ExitTransition.None) { Box(Modifier.animateEnterExit( enter = slideInVertically(tween(durationMillis = 5000)), exit = slideOutVertically(tween(durationMillis = 5000)) ).size(200.dp).background(Color.DarkGray)) } Row(Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceEvenly) { Button({boxVisible.value = true}, enabled = !boxVisible.value){ Text("Show", fontSize = 28.sp)} Button({boxVisible.value = false}, enabled = boxVisible.value){ Text("Hide", fontSize = 28.sp)} } } } } }
Здесь модификатор применяется к компоненту Box, который расположен внутри AnimatedVisibility:
AnimatedVisibility( visible = boxVisible.value, Modifier.padding(40.dp), enter = EnterTransition.None, exit = ExitTransition.None) { Box(Modifier.animateEnterExit( enter = slideInVertically(tween(durationMillis = 5000)), exit = slideOutVertically(tween(durationMillis = 5000)) ).size(200.dp).background(Color.DarkGray)) }
Видимость компонента AnimatedVisibility привязана к переменной-состоянию boxVisible, значение которой переключается кнопками.
Поскольку для управления анимацией всецело используется модификатор animateEnterExit на компоненте Box, то для AnimatedVisibility наоборот отключаем анимацию:
enter = EnterTransition.None, exit = ExitTransition.None
У компонента Box для анимации применяем функции slideInVertically
и slideOutVertically
Box(Modifier.animateEnterExit( enter = slideInVertically(tween(durationMillis = 5000)), exit = slideOutVertically(tween(durationMillis = 5000)) )
Таким образом при появлении компонент Box начнет медленно скользить сверху вниз в течение 5 секунд, а при изчезновении, наоборот, подниматься снизу вверх, пока не уйдет из области обзора.
Аналогично можно было бы определить внутри AnimatedVisibility несколько компонентов с разными типами анимаций:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent @ExperimentalAnimationApi{ val boxVisible = remember { mutableStateOf(true) } Column(Modifier.padding(20.dp), horizontalAlignment = Alignment.CenterHorizontally) { AnimatedVisibility( visible = boxVisible.value, Modifier.padding(20.dp), enter = EnterTransition.None, exit = ExitTransition.None) { Row{ Box(Modifier.animateEnterExit( enter = slideInVertically(tween(durationMillis = 5000)), exit = slideOutVertically(tween(durationMillis = 5000)) ).size(150.dp).background(Color.DarkGray)) Spacer(modifier = Modifier.width(20.dp)) Box(Modifier.animateEnterExit( enter = fadeIn(tween(durationMillis = 5000)), exit = fadeOut(tween(durationMillis = 5000)) ).size(150.dp).background(Color.DarkGray)) } } Row(Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceEvenly) { Button({boxVisible.value = true}, enabled = !boxVisible.value){ Text("Show", fontSize = 28.sp)} Button({boxVisible.value = false}, enabled = boxVisible.value){ Text("Hide", fontSize = 28.sp)} } } } } }
В данном случае в AnimatedVisibility два компонента Box с разным набором анимаций. Первый Box для создания анимации использует функции slideInVertically()
и
slideOutVertically()
, тогда как второй Box - функции fadeIn()
и fadeOut()