Optional Predictive NavAnim
This commit is contained in:
1 parent
4194087f0b
commit
2611601fb9
5 files changed
+59
-40
No files matched your search
@@ -17,6 +17,7 @@
|
||||
package androidx.navigation.compose
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.PredictiveBackHandler
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedContentTransitionScope
|
||||
@@ -53,6 +54,8 @@ import androidx.navigation.NavHostController
|
||||
import androidx.navigation.Navigator
|
||||
import androidx.navigation.createGraph
|
||||
import androidx.navigation.get
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.collectAsState
|
||||
import kotlin.math.roundToLong
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.NonCancellable
|
||||
@@ -280,54 +283,63 @@ public fun NavHost(
|
||||
}
|
||||
}
|
||||
|
||||
val duration = 500000000L
|
||||
val transitionState = remember { MutableTransitionState(backStackEntry) }
|
||||
val transition = updateTransition(transitionState = transitionState, label = "entry")
|
||||
val animatedFraction = remember { Animatable(0f).also { it.updateBounds(lowerBound = 0f, upperBound = 1f) } }
|
||||
val enablePredictiveBack by Settings.predictiveNavAnim.collectAsState()
|
||||
val transition = if (enablePredictiveBack) {
|
||||
val duration = 500000000L
|
||||
val transitionState = remember { MutableTransitionState(backStackEntry) }
|
||||
val transition = updateTransition(transitionState = transitionState, label = "entry")
|
||||
val animatedFraction = remember { Animatable(0f).also { it.updateBounds(lowerBound = 0f, upperBound = 1f) } }
|
||||
|
||||
fun seekToFraction(lState: NavBackStackEntry, rState: NavBackStackEntry) {
|
||||
val fraction = animatedFraction.value
|
||||
val playTimeNanos = (fraction * duration).roundToLong()
|
||||
transition.setPlaytimeAfterInitialAndTargetStateEstablished(lState, rState, playTimeNanos)
|
||||
}
|
||||
fun seekToFraction(lState: NavBackStackEntry, rState: NavBackStackEntry) {
|
||||
val fraction = animatedFraction.value
|
||||
val playTimeNanos = (fraction * duration).roundToLong()
|
||||
transition.setPlaytimeAfterInitialAndTargetStateEstablished(lState, rState, playTimeNanos)
|
||||
}
|
||||
|
||||
LaunchedEffect(backStackEntry) {
|
||||
try {
|
||||
animatedFraction.animateTo(1f, animationSpec = tween(500, easing = LinearEasing)) {
|
||||
seekToFraction(transitionState.currentState, backStackEntry)
|
||||
}
|
||||
} finally {
|
||||
withContext(NonCancellable) {
|
||||
animatedFraction.snapTo(0f)
|
||||
transition.setPlaytimeAfterInitialAndTargetStateEstablished(
|
||||
backStackEntry,
|
||||
backStackEntry,
|
||||
0,
|
||||
)
|
||||
LaunchedEffect(backStackEntry) {
|
||||
try {
|
||||
animatedFraction.animateTo(1f, animationSpec = tween(500, easing = LinearEasing)) {
|
||||
seekToFraction(transitionState.currentState, backStackEntry)
|
||||
}
|
||||
} finally {
|
||||
withContext(NonCancellable) {
|
||||
animatedFraction.snapTo(0f)
|
||||
transition.setPlaytimeAfterInitialAndTargetStateEstablished(
|
||||
backStackEntry,
|
||||
backStackEntry,
|
||||
0,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PredictiveBackHandler(currentBackStack.size > 1) { flow ->
|
||||
// Prev can never be null, i.e. BackHandler should not enabled when prev is null
|
||||
val prev = currentBackStack.last { it != backStackEntry }
|
||||
try {
|
||||
flow.collect {
|
||||
val interpolated = EaseOut.transform(it.progress)
|
||||
animatedFraction.snapTo(interpolated)
|
||||
seekToFraction(backStackEntry, prev)
|
||||
PredictiveBackHandler(currentBackStack.size > 1) { flow ->
|
||||
// Prev can never be null, i.e. BackHandler should not enabled when prev is null
|
||||
val prev = currentBackStack.last { it != backStackEntry }
|
||||
try {
|
||||
flow.collect {
|
||||
val interpolated = EaseOut.transform(it.progress)
|
||||
animatedFraction.snapTo(interpolated)
|
||||
seekToFraction(backStackEntry, prev)
|
||||
}
|
||||
navController.popBackStack()
|
||||
} catch (e: CancellationException) {
|
||||
withContext(NonCancellable) {
|
||||
animatedFraction.snapTo(0f)
|
||||
transition.setPlaytimeAfterInitialAndTargetStateEstablished(
|
||||
backStackEntry,
|
||||
backStackEntry,
|
||||
0,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
transition
|
||||
} else {
|
||||
BackHandler(currentBackStack.size > 1) {
|
||||
navController.popBackStack()
|
||||
} catch (e: CancellationException) {
|
||||
withContext(NonCancellable) {
|
||||
animatedFraction.snapTo(0f)
|
||||
transition.setPlaytimeAfterInitialAndTargetStateEstablished(
|
||||
backStackEntry,
|
||||
backStackEntry,
|
||||
0,
|
||||
)
|
||||
}
|
||||
}
|
||||
updateTransition(backStackEntry, label = "entry")
|
||||
}
|
||||
|
||||
transition.AnimatedContent(
|
||||
|
||||
@@ -106,6 +106,7 @@ object Settings : DataStorePreferences(null) {
|
||||
val thumbColumns = intPref("thumb_columns", 3)
|
||||
val listThumbSize = intPref("list_tile_size", 40)
|
||||
val meteredNetworkWarning = boolPref("cellular_network_warning", false)
|
||||
val predictiveNavAnim = boolPref("predictive_nav_anim", true)
|
||||
|
||||
val needSignInFlow: Flow<Boolean>
|
||||
var downloadScheme by stringOrNullPref("image_scheme", null)
|
||||
|
||||
@@ -141,6 +141,10 @@ fun AdvancedScreen(navigator: DestinationsNavigator) {
|
||||
title = stringResource(id = R.string.preload_thumb_aggressively),
|
||||
value = Settings::preloadThumbAggressively,
|
||||
)
|
||||
SwitchPreference(
|
||||
title = stringResource(id = R.string.predictive_nav_anim),
|
||||
value = Settings.predictiveNavAnim::value,
|
||||
)
|
||||
IntSliderPreference(
|
||||
maxValue = 5,
|
||||
minValue = 1,
|
||||
|
||||
@@ -524,6 +524,7 @@
|
||||
<string name="list_tile_thumb_size">详情模式下缩略图大小</string>
|
||||
<string name="account_name">账户</string>
|
||||
<string name="preload_thumb_aggressively">激进地预载缩略图</string>
|
||||
<string name="predictive_nav_anim">启用预见式返回导航动画</string>
|
||||
<string name="auto_updates">自动检查更新</string>
|
||||
<string name="update_frequency_never">从不</string>
|
||||
<string name="update_frequency_daily">每天</string>
|
||||
|
||||
@@ -587,6 +587,7 @@
|
||||
<string name="list_tile_thumb_size">Thumb size in thumb mode</string>
|
||||
<string name="account_name">Account</string>
|
||||
<string name="preload_thumb_aggressively">Preload thumbs aggressively</string>
|
||||
<string name="predictive_nav_anim">Enable predictive back navigation animation</string>
|
||||
<string name="user_agent">User Agent</string>
|
||||
<string name="auto_updates">Automatically check for updates</string>
|
||||
<string name="update_frequency_never">Never</string>
|
||||
|
||||
Reference in new issue
Block a user