Как сделать анимацию для custom HorizontalPager dot indicator?

У меня есть достаточно простой код который отображает HorizontalPager и DotIndicator вот здесь:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Text
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.google.accompanist.pager.*

@Composable
fun HorizontalPagerWithCustomDotIndicator() {
    val pageCount = 5  // Total number of pages
    val pagerState = rememberPagerState()

    Column(modifier = Modifier.fillMaxSize()) {
        HorizontalPager(
            count = pageCount,
            state = pagerState,
            modifier = Modifier.weight(1f)
        ) { page ->
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .background(if (page % 2 == 0) Color.Gray else Color.LightGray),
                contentAlignment = Alignment.Center
            ) {
                Text(text = "Page ${page + 1}", style = MaterialTheme.typography.h4)
            }
        }

        DotIndicator(
            modifier = Modifier
                .align(Alignment.CenterHorizontally)
                .padding(vertical = 16.dp),
            pagesNumber = pageCount,
            isItemSelectedByIdx = { idx -> idx == pagerState.currentPage }
        )
    }
}

@Composable
fun DotIndicator(
    modifier: Modifier = Modifier,
    pagesNumber: Int,
    isItemSelectedByIdx: (idx: Int) -> Boolean = { false },
) {
    LazyRow(
        modifier = modifier
            .wrapContentHeight()
            .wrapContentWidth(),
        horizontalArrangement = Arrangement.spacedBy(
            space = 8.dp,  // Adjust spacing as necessary
            alignment = Alignment.CenterHorizontally
        ),
    ) {
        repeat(pagesNumber) { idx ->
            item {
                val isSelected: Boolean = isItemSelectedByIdx(idx)
                val color by animateColorAsState(targetValue = if (isSelected) Color.White else Color.Gray)

                Box(
                    modifier = Modifier
                        .background(color, CircleShape)
                        .size(8.dp)
                )
            }
        }
    }
}

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

Теперь как происходит перемещение цвета, просто отслеживается активная позиция Pager и соответственно к выбраной позиции применяется белый цвет, а ко все остальным (не активным) серый.

Что нужно сделать - нужно сделать анимацию при которой цвет с будет перемещаться на следующую выбраную позицию с анимацией, как капля которая с одной позиции перемещает свой цвет на следующую.

Если это описывать словами, то представим, что юзер делает свайп слева на право и визуально должен получиться эффект как будто левая точка растягивается вправо до правой точки и потом как подтягивает "хвост" слева к правой точке, то есть получается как будто такой эффект капли что ли.


Ответы (0 шт):