September 20

Создаем мерцающий текст в Jetpack Compose

В этой статье мы создадим потрясающую анимацию мерцающего текста в Jetpack Compose, идеально подходящую для минималистичного загрузчика.

Определение функции

Начнем с определения Composable функции ShimmeringText:

@Composable
fun ShimmeringText(
    text: String,
    shimmerColor: Color,
    modifier: Modifier = Modifier,
    textStyle: TextStyle = LocalTextStyle.current,
    animationSpec: DurationBasedAnimationSpec<Float> = tween(1000, 500, LinearEasing)
)

Параметры:

  • text — текст, который будет отображаться
  • shimmerColor — цвет, используемый для эффекта мерцания
  • modifier — модификатор, который будет применен к тексту
  • textStyle — стиль текста
  • animationSpec — спецификация анимации для управления скоростью, задержкой и смягчением мерцания.

Реализация функции

Создание бесконечной анимации

Сначала мы определим бесконечный анимационный переход:

val infiniteTransition = rememberInfiniteTransition(label = "ShimmeringTextTransition")

Используя этот переход, мы создаем анимацию shimmerProgress, которая движется от 0 до 1 и повторяется:

val shimmerProgress by infiniteTransition.animateFloat(
    initialValue = 0f,
    targetValue = 1f,
    animationSpec = infiniteRepeatable(animationSpec),
    label = "ShimmerProgress"
)

Создание мерцающей кисти

Далее мы создадим мерцающую кисть, которая будет перемещаться по тексту в зависимости от значения shimmerProgress:

val brush = remember(shimmerProgress) {
    object : ShaderBrush() {
        override fun createShader(size: Size): Shader {
            // Define the starting X offset, beginning outside the left edge of the text
            val initialXOffset = -size.width
            // Total distance the shimmer will sweep across (double the text width for full coverage)
            val totalSweepDistance = size.width * 2
            // Calculate the current position of the shimmer based on the animation progress
            val currentPosition = initialXOffset + totalSweepDistance * shimmerProgress
            return LinearGradientShader(
                colors = listOf(Color.Transparent, shimmerColor, Color.Transparent),
                from = Offset(currentPosition, 0f),
                to = Offset(currentPosition + size.width, 0f)
            )
        }
    }
}

Рендеринг текста

Наконец, мы отрендерим композабл Text с анимированной мерцающей кистью:

Text(
    text = text,
    modifier = modifier,
    style = textStyle.copy(brush = brush)
)

Вот и все, мы успешно создали компонент. Полный код вы можете найти на GitHub. Давайте изучим возможности использования.

Пример использования

Для примера создадим простую анимацию загрузки:

Box(
    modifier = Modifier
        .fillMaxSize()
        .background(Color.Black),
    contentAlignment = Alignment.Center
) {
    ShimmeringText(
        text = "LOADING",
        shimmerColor = Color.White,
        textStyle = LocalTextStyle.current.copy(
            fontSize = 20.sp,
            letterSpacing = 5.sp,
            fontWeight = FontWeight.Bold
        )
    )
}

Вот что получится:

(Источник)