Add rotate inertia for favSelectDialog

This commit is contained in:
FooIbar authored and Vladimir Dostoyevskiy committed 2023-11-16 23:15:02 +08:00
1 parent fa2933df7c
commit aa50b69754
1 file changed
+27 -1
@@ -1,9 +1,14 @@
package com.hippo.ehviewer.ui.tools
import androidx.compose.animation.core.FloatExponentialDecaySpec
import androidx.compose.animation.core.animateDecay
import androidx.compose.foundation.gestures.draggable2D
import androidx.compose.foundation.gestures.rememberDraggable2DState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
@@ -14,6 +19,8 @@ import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.roundToInt
import kotlin.math.sin
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
private const val FULL_CIRCLE: Float = (PI * 2).toFloat()
private const val QUARTER_CIRCLE = PI / 2
@@ -21,13 +28,17 @@ private const val QUARTER_CIRCLE = PI / 2
private var currentTheta: Float? = null
private var currentOfs: Offset? = null
private val rotateDecay = FloatExponentialDecaySpec()
private var animJob: Job? = null
@Composable
fun CircularLayout(
modifier: Modifier = Modifier,
placeFirstItemInCenter: Boolean = false,
content: @Composable () -> Unit,
) {
var delta by Settings::favDialogTheta.observed
val coroutineScope = rememberCoroutineScope()
var delta by remember { mutableFloatStateOf(Settings.favDialogTheta) }
val state = rememberDraggable2DState {
val prevOfs = currentOfs
val prevTheta = currentTheta
@@ -46,12 +57,27 @@ fun CircularLayout(
onDragStarted = {
// Get relative offset to center
val ofs = it - Offset(500f, 500f)
animJob?.cancel()
currentOfs = ofs
currentTheta = atan2(ofs.y, ofs.x)
},
onDragStopped = {
val current = currentOfs
if (current != null) {
val dist = current.getDistance()
val tanVec = Offset(-current.y / dist, current.x / dist)
val tanV = it.x * tanVec.x + it.y * tanVec.y
val omega = tanV / dist
animJob = coroutineScope.launch {
animateDecay(delta, omega, rotateDecay) { d, _ ->
delta = d
}
Settings.favDialogTheta = delta
}
}
currentOfs = null
currentTheta = null
Settings.favDialogTheta = delta
},
),
content = content,