Remove unused class HorizontalTabPager
This commit is contained in:
@@ -1,172 +0,0 @@
|
|||||||
package it.vfsfitvnm.vimusic.ui.components
|
|
||||||
|
|
||||||
import androidx.compose.animation.core.Animatable
|
|
||||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
|
||||||
import androidx.compose.animation.core.calculateTargetValue
|
|
||||||
import androidx.compose.animation.core.tween
|
|
||||||
import androidx.compose.animation.splineBasedDecay
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
||||||
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
|
|
||||||
import androidx.compose.foundation.lazy.layout.LazyLayout
|
|
||||||
import androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider
|
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.clipToBounds
|
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
|
||||||
import androidx.compose.ui.input.pointer.util.VelocityTracker
|
|
||||||
import androidx.compose.ui.input.pointer.util.addPointerInputChange
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlin.math.absoluteValue
|
|
||||||
|
|
||||||
|
|
||||||
@Stable
|
|
||||||
class TabPagerState(
|
|
||||||
val pageCount: Int,
|
|
||||||
val initialPageIndex: Int,
|
|
||||||
) {
|
|
||||||
var pageIndex by mutableStateOf(initialPageIndex)
|
|
||||||
|
|
||||||
var tempPageIndex: Int? = null
|
|
||||||
|
|
||||||
val animatable = Animatable(0f)
|
|
||||||
|
|
||||||
val offset by animatable.asState()
|
|
||||||
|
|
||||||
fun updateBounds(lowerBound: Float, upperBound: Float) {
|
|
||||||
animatable.updateBounds(lowerBound, upperBound)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun animateScrollTo(newPageIndex: Int) {
|
|
||||||
tempPageIndex = newPageIndex
|
|
||||||
if (newPageIndex > pageIndex) {
|
|
||||||
animatable.animateTo(
|
|
||||||
animatable.upperBound!!, tween(
|
|
||||||
durationMillis = 300,
|
|
||||||
easing = FastOutSlowInEasing
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else if (newPageIndex < pageIndex) {
|
|
||||||
animatable.animateTo(
|
|
||||||
animatable.lowerBound!!, tween(
|
|
||||||
durationMillis = 300,
|
|
||||||
easing = FastOutSlowInEasing
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pageIndex = newPageIndex
|
|
||||||
animatable.snapTo(0f)
|
|
||||||
tempPageIndex = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun rememberTabPagerState(initialPageIndex: Int, pageCount: Int): TabPagerState {
|
|
||||||
return remember {
|
|
||||||
TabPagerState(
|
|
||||||
pageCount = pageCount,
|
|
||||||
initialPageIndex = initialPageIndex,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
fun HorizontalTabPager(
|
|
||||||
state: TabPagerState,
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
content: @Composable (index: Int) -> Unit
|
|
||||||
) {
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
val itemProvider = remember(state) {
|
|
||||||
object : LazyLayoutItemProvider {
|
|
||||||
override val itemCount = state.pageCount
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
override fun Item(index: Int) = content(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLayout(
|
|
||||||
itemProvider = itemProvider,
|
|
||||||
modifier = modifier
|
|
||||||
.clipToBounds()
|
|
||||||
.pointerInput(state) {
|
|
||||||
val velocityTracker = VelocityTracker()
|
|
||||||
val decay = splineBasedDecay<Float>(this)
|
|
||||||
|
|
||||||
detectHorizontalDragGestures(
|
|
||||||
onHorizontalDrag = { change, dragAmount ->
|
|
||||||
velocityTracker.addPointerInputChange(change)
|
|
||||||
coroutineScope.launch {
|
|
||||||
state.animatable.snapTo(state.offset - dragAmount)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onDragEnd = {
|
|
||||||
val velocity = -velocityTracker.calculateVelocity().x
|
|
||||||
val initialTargetValue =
|
|
||||||
decay.calculateTargetValue(state.offset, velocity)
|
|
||||||
|
|
||||||
velocityTracker.resetTracking()
|
|
||||||
|
|
||||||
coroutineScope.launch {
|
|
||||||
val isEnough = initialTargetValue.absoluteValue > size.width / 2
|
|
||||||
if (initialTargetValue > 0) {
|
|
||||||
state.animatable.animateTo(
|
|
||||||
targetValue = if (isEnough) size.width.toFloat() else 0f,
|
|
||||||
initialVelocity = if (isEnough) velocity else 0f
|
|
||||||
)
|
|
||||||
if (isEnough) {
|
|
||||||
state.pageIndex = state.pageIndex
|
|
||||||
.plus(1)
|
|
||||||
.coerceAtMost(state.pageCount - 1)
|
|
||||||
state.animatable.snapTo(0f)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
state.animatable.animateTo(
|
|
||||||
targetValue = if (isEnough) -size.width.toFloat() else 0f,
|
|
||||||
initialVelocity = if (isEnough) velocity else 0f
|
|
||||||
)
|
|
||||||
if (isEnough) {
|
|
||||||
state.pageIndex = state.pageIndex
|
|
||||||
.minus(1)
|
|
||||||
.coerceAtLeast(0)
|
|
||||||
state.animatable.snapTo(0f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { constraints ->
|
|
||||||
val previousPlaceable = state.offset.takeIf { it < 0 }?.let {
|
|
||||||
(state.tempPageIndex ?: (state.pageIndex - 1)).takeIf { it >= 0 }?.let { index ->
|
|
||||||
measure(index, constraints).first()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val placeable = measure(state.pageIndex, constraints).first()
|
|
||||||
|
|
||||||
val nextPlaceable = state.offset.takeIf { it > 0 }?.let {
|
|
||||||
(state.tempPageIndex ?: (state.pageIndex + 1)).takeIf { it < state.pageCount }
|
|
||||||
?.let { index ->
|
|
||||||
measure(index, constraints).first()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.updateBounds(
|
|
||||||
lowerBound = if (state.pageIndex == 0) 0f else -constraints.maxWidth.toFloat(),
|
|
||||||
upperBound = if (state.pageIndex == state.pageCount - 1) 0f else constraints.maxWidth.toFloat()
|
|
||||||
)
|
|
||||||
|
|
||||||
layout(width = constraints.maxWidth, height = constraints.maxHeight) {
|
|
||||||
previousPlaceable?.let {
|
|
||||||
previousPlaceable.place(x = -state.offset.toInt() - constraints.maxWidth, y = 0)
|
|
||||||
placeable.place(x = -state.offset.toInt(), y = 0)
|
|
||||||
} ?: nextPlaceable?.let {
|
|
||||||
placeable.place(x = -state.offset.toInt(), y = 0)
|
|
||||||
nextPlaceable.place(x = -state.offset.toInt() + constraints.maxWidth, y = 0)
|
|
||||||
} ?: placeable.place(x = -state.offset.toInt(), y = 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user