Анимация с помощью Jetpack Compose — часть 3
Jetpack Compose — это революционное обновление для создания пользовательского интерфейса Android-приложения. Он использовал концепцию декларативного пользовательского интерфейса и приносил удовольствие от создания пользовательского интерфейса с помощью Kotlin — мечта многих разработчиков Android. Если вы новичок в Jetpack Compose, я рекомендую вам ознакомиться со следующими статьями:
Чтобы узнать больше об анимациях в Jetpack Compose, прочитайте следующую статью из этой серии анимаций:
- «Jetpack Compose — Animated Notes: 1 — Изучение AnimatedVisibility в Compose»
- «Jetpack Compose — Animation Notes: 2 — Создание великолепного меню с Compose AnimatedVisibility и Animatable»
- «Jetpack Compose — Animation Notes: 3» — Вы здесь и сейчас
С учетом сказанного, давайте начнем.
Введение
Какова цель?
Мы пытаемся реализовать анимацию обновления кнопки, которая включает масштабирование текста и значка с бесконечным вращением. Взгляни:
LaunchedEffect
LaunchedEffect
— составная функция с двумя параметрами — Key1 и block.
key1
— имеет типAny
, всякий раз, когда значение, переданное в этом параметре, изменяется, вызывается функцияblock
.block
— функция Kotlinsuspend
с собственной областью сопрограммы. Текущая область отменяется и перезапускается всякий раз, когда обновляется значениеkey1
. Сопрограмма будет отменена, когда LaunchedEffect покинет композицию.
Взгляните на сигнатуру функции:
@Composable @NonRestartableComposable @OptIn(InternalComposeApi::class) fun LaunchedEffect( key1: Any?, block: suspend CoroutineScope.() -> Unit )
В нашем случае мы можем использовать функцию LaunchedEffect
для выполнения анимации при начальной компоновке или рекомпозиции, вызванной любым изменением состояния.
Бесконечный переход
InfiniteTransition
отвечает за запуск дочерних анимаций. Используя rememberInfiniteTransition
, мы можем запускать бесконечные дочерние анимации. В нашем случае мы можем использовать это для бесконечного вращения значка загрузки.
Состояние кнопки
Давайте создадим класс перечисления с двумя состояниями, текстом и значком, чтобы отображать текст или значок на кнопке. Давайте также создадим функцию расширения для возврата противоположного состояния, которую можно использовать для обновления состояния при действии пользователя. Взгляни:
enum class ButtonState{ TEXT, ICON } fun ButtonState.getOppositeState() : ButtonState = when(this){ ButtonState.TEXT -> ButtonState.ICON ButtonState.ICON -> ButtonState.TEXT }
Кнопка обновления дизайна
Чтобы спроектировать кнопку обновления, мы использовали компонуемый элемент Box
в качестве корня, потому что в любой момент будут отображаться только Text
или Icon
. Взгляните на код:
Добавьте следующий цвет в класс проекта color.kt
:
val GreenButton = Color(0xFF00914b)
Посмотрите на вывод:
Прежде чем перейти к части анимации, во-первых, нам нужно удалить эффект пульсации, так как он не будет соответствовать нашей пользовательской анимации. Мы можем добиться этого, создав любое расширение для Modifier
и обработав параметры indication
и interactionSource
функции clickable
, как показано ниже:
Теперь мы можем использовать функцию clickableNoRipple
вместо clickable
в корневом компоненте Box
.
Бесконечное вращение
Давайте начнем с более простой анимации, где мы должны вращать значок обновления, как только состояние кнопки изменится на ICON
. Для этого мы должны использовать функцию расширения rotate
для Modifer
, обернутую значком. rotate
принимает float
в качестве параметра, указывающего на градусы поворота.
Сложность здесь заключается в том, чтобы вычислить градусы, rememberInfiniteTransition
подходит для этой цели. Давайте создадим отдельный составной объект для создания и поддержки этого перехода. Взгляни:
animateFloat
— это функция расширения на InfiniteTransition
. Он имеет три параметра:
initialValue
— Значение с плавающей запятой для указания начальной степени.targetValue
— число с плавающей запятой для указания градусов к концу анимации.animationSpec
— Параметр для указания особенностей анимации. В нашем случаеinfiniteRepeatable
и использованиеtween
для управления продолжительностью, а также режимом повтора.
Как уже говорилось, мы должны использовать rotateComposable
с Modifier
, прикрепленным к окну значка, которое можно компоновать. Взгляни:
Посмотрите на вывод:
Масштабирование анимации с помощью LaunchedEffect
Начнем с трех аспектов, требующих анимации: текста, масштабирования значков и изменения содержимого текста. Для части масштабирования мы можем использовать Animatable
с remember
, а для части контента мы можем использовать mutableStateOf
. Посмотрите:
val scaleText = remember{ Animatable(initialValue = 1f) } val scaleIcon = remember{ Animatable(initialValue = 0f) } var displayString by remember { mutableStateOf("Refresh")}
Первоначально будет отображаться компонуемый Text
, поэтому initialValue
из scaleText
будет 1f
. Принимая во внимание, что scaleIcon
— это 0f
, так как оно будет скрыто.
Давайте создадим простую функцию Composable
с refershScalingAnimation
, которая принимает два параметра:
buttonState
— для выполнения соответствующей анимации масштабирования и изменения содержимого.isSelected
— параметрBoolean
для использования в качестве ключаLaunchedEffect
.
Взгляни:
Теперь мы должны использовать функцию animateTo
для scaleText
и scaleIcon
для запуска анимации масштабирования в соответствующих блоках. Если состояние кнопки ICON
, то мы должны начать с scaleText
с targetValue
как 0f
, затем обновить displayString
до пустого и, наконец, масштабировать значок от 1f
до scaleIcon
. Если buttonState
равно TEXT
, мы должны обратить анимацию. Взгляни:
Последним шагом является использованиеscaleText
и scaleIcon
с модификаторами, примененными к составным функциям Text
и Icon
. Поскольку мы создали отдельную функцию для анимации LaunchedEffect
, мы должны вернуть scaleText
, scaleIcon
и displayString
, чтобы использовать их с соответствующими составными функциями. Посмотрите на полную функцию:
Теперь давайте вызовем refershScalingAnimation
из ButtonRefresh
и применим scaleText
, scaleIcon
и displayString
к соответствующим составным функциям. Взгляни:
Посмотрите на вывод:
Заключение
Вот и все. Мы реализовали пользовательскую анимацию кнопки обновления с LaunchedEffect
и InfiniteTransition
составными функциями. Пожалуйста, нажмите здесь, чтобы просмотреть полный код. Анимация — интересная тема для изучения в Jetpack Compose, позволяющая сделать пользовательский интерфейс более плавным. Следите за новыми статьями об анимации в Jetpack Compose.
Бонус
Это все на данный момент. Надеюсь, вы узнали что-то полезное. Спасибо за прочтение.