Анимация сенсорной обратной связи, как у Spotify в Jetpack Compose

May 04 2023
Создайте эффект прыгающего клика в Jetpack Compose
Крайне важно показать пользователю обратную связь о кликах, бла-бла-бла. Короче говоря, мне нравится эффект отскакивающего клика Spotify больше, чем эффект Ripple по умолчанию, поэтому давайте сделаем это Попутно мы изучим некоторые модификаторы и анимацию… Чтобы сделать это, мы создайте многоразовый модификатор (похожий на кликабельный модификатор), который уменьшает масштаб и непрозрачность при нажатии на элемент пользовательского интерфейса. Я продолжу и приведу весь код, а затем объясню его… Вот и все, давайте использовать его Вот и все, я надеюсь вам понравился блог ❤️.

Очень важно показать пользователю отзыв о клике, бла-бла-бла. Короче говоря, мне нравится эффект прыгающего клика Spotify больше, чем эффект Ripple по умолчанию, так что давайте сделаем это

Попутно мы изучим некоторые модификаторы и анимацию…

Это похоже на настоящую кнопку, верно? :)

Для этого мы создадим многоразовый Modifierмодификатор (похожий на кликабельный), который уменьшает масштаб и непрозрачность при нажатии на элемент пользовательского интерфейса.
Я продолжу и приведу весь код, а затем объясню его…

/**
 * Adds a bouncing click effect to a Composable.
 *
 * @param enabled whether the UI element should be enabled and clickable
 * @param onClick the action to perform when the UI element is clicked
 */
fun Modifier.bouncingClickable(
    enabled: Boolean = true,
    onClick: () -> Unit
) = composed {
    val interactionSource = remember { MutableInteractionSource() }
    val isPressed by interactionSource.collectIsPressedAsState()

    val animationTransition = updateTransition(isPressed, label = "BouncingClickableTransition")
    val scaleFactor by animationTransition.animateFloat(
        targetValueByState = { pressed -> if (pressed) 0.94f else 1f },
        label = "BouncingClickableScaleFactorTransition",
    )
    val opacity by animationTransition.animateFloat(
        targetValueByState = { pressed -> if (pressed) 0.7f else 1f },
        label = "BouncingClickableOpacityTransition"
    )

    this
        .graphicsLayer {
            this.scaleX = scaleFactor
            this.scaleY = scaleFactor
            this.alpha = opacity
        }
        .clickable(
            interactionSource = interactionSource,
            indication = null,
            enabled = enabled,
            onClick = onClick
        )
}

  1. Затем, поскольку у нас есть несколько анимаций, которые мы хотим запустить, когда isPressed == true, мы используем updateTransition()это, предоставляя нам функции расширения для запуска нескольких анимаций.
  2. Чтобы создать анимацию, мы используем animateFloat()расширение для создания двух анимаций, одну для scaleFactorи одну для opacity того, что мы будем использовать для анимации нашего элемента пользовательского интерфейса.
  3. Чтобы изменить масштаб и альфа-канал, мы использовали graphicsLayerмодификатор, который обычно используется для применения преобразований и анимации к элементу пользовательского интерфейса. ( прочитайте эту замечательную статью, чтобы узнать больше )
  4. Наконец, мы добавляем модификатор clickable для обработки щелчка и удаляем эффект ряби по умолчанию, установив indicationдля параметра значениеnull

Вот и все, воспользуемся

Box(
    modifier = Modifier
        .bouncingClickable {
            println("Clicked...")
        }
        .size(100.dp)
        .clip(CircleShape)
        .background(Color.Black)
) {}

      
                

val scaleFactor by animationTransition.animateFloat(
    targetValueByState = { pressed -> if (pressed) 0.94f else 1f },
    label = "BouncingClickableScaleFactorTransition",
    transitionSpec = {
        spring(
            dampingRatio = Spring.DampingRatioMediumBouncy,
            stiffness = Spring.StiffnessLow
        )
    }
)

      
                

Вот и все, надеюсь, вам понравился блог ❤️