Анимация с помощью Jetpack Compose — часть 3

Jetpack Compose — это революционное обновление для создания пользовательского интерфейса Android-приложения. Он использовал концепцию декларативного пользовательского интерфейса и приносил удовольствие от создания пользовательского интерфейса с помощью Kotlin — мечта многих разработчиков Android. Если вы новичок в Jetpack Compose, я рекомендую вам ознакомиться со следующими статьями:

Чтобы узнать больше об анимациях в Jetpack Compose, прочитайте следующую статью из этой серии анимаций:

С учетом сказанного, давайте начнем.

Введение

Какова цель?

Мы пытаемся реализовать анимацию обновления кнопки, которая включает масштабирование текста и значка с бесконечным вращением. Взгляни:

LaunchedEffect

LaunchedEffect — составная функция с двумя параметрами — Key1 и block.

  1. key1 — имеет тип Any, всякий раз, когда значение, переданное в этом параметре, изменяется, вызывается функция block.
  2. block — функция Kotlin suspend с собственной областью сопрограммы. Текущая область отменяется и перезапускается всякий раз, когда обновляется значение 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. Он имеет три параметра:

  1. initialValue — Значение с плавающей запятой для указания начальной степени.
  2. targetValue — число с плавающей запятой для указания градусов к концу анимации.
  3. 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, которая принимает два параметра:

  1. buttonState — для выполнения соответствующей анимации масштабирования и изменения содержимого.
  2. 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.

Бонус



Это все на данный момент. Надеюсь, вы узнали что-то полезное. Спасибо за прочтение.