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

Создано автором

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

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

@Composable
fun SpinningCirclesLoader(
modifier: Modifier,
centerColor: Color = Color.Black,
circleColors: List<Color> = listOf(Color.Red, Color.Green, Color.Blue),
spec: DurationBasedAnimationSpec<Float> = tween(800, easing = LinearEasing)
)

Параметры

  •  modifier: модификатор, применяемый к холсту (canvas), на котором происходит анимация;
  •  centerColor: цвет центральной статической точки;
  •  circleColors: список цветов для вращающихся кругов (каждый цвет в списке соответствует кругу в загрузчике);
  •  spec: спецификация анимации для цикла вращения.

Реализация

1. Определение логики вращающегося круга

Абстрагируем логику рисования вращающегося круга в отдельную функцию:

fun DrawScope.drawRotatingCircle(
degree: Float,
radius: Float,
centerPadding: Float,
strokeWidth: Float,
color: Color
) {
// Преобразование градусов в радианы для вычислений
val radians = Math.toRadians(degree.toDouble()).toFloat()

// Настройка радиуса для отступа и ширины штриха
val circleCenterRadius = radius - centerPadding - strokeWidth / 2

// Вычисление координаты X круга
val circleX = center.x + circleCenterRadius * cos(radians)

// Вычисление координаты Y круга
val circleY = center.y + circleCenterRadius * sin(radians)

// Отрисовка вращающегося круга
drawCircle(
color = color,
radius = radius,
center = Offset(circleX, circleY),
style = Stroke(strokeWidth)
)
}

2. Определение угла вращения

Чтобы заставить круги двигаться, создадим бесконечную анимацию, которая проходит от 0 до 360 градусов и повторяется:

val transition = rememberInfiniteTransition(label = "RotationTransition")
val degree by transition.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(spec),
label = "RotationDegree"
)

3. Выполнение анимации с вращающимися кругами

Наконец, можем использовать Composable-функцию Canvas для выполнения анимации:

Canvas(modifier) {
// Определение радиуса центрального круга
val pointRadius = size.minDimension * 0.1f

// Определение радиуса вращающихся кругов
val circleRadius = size.minDimension / 4

// Определение ширины штриха для вращающихся кругов
val strokeWidth = size.minDimension * 0.03f

// Отрисовка центрального статического круга
drawCircle(
color = centerColor,
radius = pointRadius
)

// Проверка наличия вращающихся кругов для отрисовки
if (circleColors.isNotEmpty()) {
// Вычисление углового шага между каждым вращающимся кругом
val degreeStep = 360f / circleColors.size

// Отрисовка каждого вращающегося круга своим цветом
for (circle in circleColors.indices) {
val baseAngle = degreeStep * circle
drawRotatingCircle(baseAngle + degree, circleRadius, pointRadius, strokeWidth, circleColors[circle])
}
}
}

Анимация успешно создана. Полный код можно найти на GitHub Gist. А теперь изучим возможности использования.

Практическое применение

Функция SpinningCirclesLoader довольно проста в применении. Рассмотрим несколько вариантов использования:

// Один круг
SpinningCirclesLoader(
modifier = Modifier.size(100.dp),
circleColors = listOf(Color.Red)
)

// Два круга
SpinningCirclesLoader(
modifier = Modifier.size(100.dp),
circleColors = listOf(Color.Yellow, Color.Blue)
)

// Три круга (по умолчанию)
SpinningCirclesLoader(Modifier.size(100.dp))

// Четыре круга
SpinningCirclesLoader(
modifier = Modifier.size(100.dp),
circleColors = listOf(Color.Red, Color.Green, Color.Blue, Color.Yellow)
)

// Пользовательское упрощение
SpinningCirclesLoader(
modifier = Modifier.size(100.dp),
spec = tween(800, easing = FastOutLinearInEasing)

Вывод:

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Kappdev: How to Create a Spinning Circles Loader in Jetpack Compose

Предыдущая статья10 полезных библиотек для фронтенд-разработки
Следующая статьяЗачем изучать Linux?