Animate settings dialog

This commit is contained in:
Niels van Velzen authored and Niels van Velzen committed 2026-01-01 18:05:20 +01:00
1 parent 875f094ff2
commit 4f67eeb0d2
3 files changed
+52 -10

No files matched your search

@@ -1,7 +1,13 @@
package org.jellyfin.androidtv.ui.base.dialog
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.focusGroup
import androidx.compose.foundation.layout.Box
@@ -10,7 +16,9 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
@@ -24,15 +32,20 @@ fun DialogBase(
visible: Boolean,
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
enterTransition: EnterTransition = fadeIn(tween(300)),
exitTransition: ExitTransition = fadeOut(tween(300)),
contentAlignment: Alignment = Alignment.Center,
content: @Composable BoxScope.() -> Unit,
) {
val transition = updateTransition(visible)
val alpha by transition.animateFloat(
transitionSpec = { tween(1000) },
targetValueByState = { visible -> if (visible) 1f else 0f }
)
if (alpha != 0f) {
if (transition.currentState || transition.isRunning) {
val focusRequester = remember { FocusRequester() }
var contentVisible by remember { mutableStateOf(false) }
Dialog(
onDismissRequest = onDismissRequest,
@@ -50,14 +63,19 @@ fun DialogBase(
.background(scrimColor.copy(alpha = scrimColor.alpha * alpha))
.focusRequester(focusRequester)
.focusGroup(),
contentAlignment = Alignment.Center,
contentAlignment = contentAlignment,
) {
content()
transition.AnimatedVisibility(
visible = { it && contentVisible },
enter = enterTransition,
exit = exitTransition,
) {
content()
}
}
}
LaunchedEffect(focusRequester) {
focusRequester.requestFocus()
}
LaunchedEffect(focusRequester) { focusRequester.requestFocus() }
LaunchedEffect(contentVisible) { contentVisible = true }
}
}
@@ -1,5 +1,11 @@
package org.jellyfin.androidtv.ui.settings.composable
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@@ -13,15 +19,26 @@ fun SettingsDialog(
modifier: Modifier = Modifier,
screen: @Composable BoxScope.() -> Unit,
) {
val duration = 400
DialogBase(
visible = visible,
onDismissRequest = onDismissRequest,
modifier = modifier,
contentAlignment = Alignment.TopEnd,
enterTransition = slideInHorizontally(
initialOffsetX = { it },
animationSpec = tween(duration, easing = FastOutSlowInEasing)
) + fadeIn(
animationSpec = tween(duration)
),
exitTransition = slideOutHorizontally(
targetOffsetX = { it },
animationSpec = tween(duration, easing = FastOutSlowInEasing)
) + fadeOut(
animationSpec = tween(duration)
),
) {
SettingsLayout(
modifier = Modifier
.align(Alignment.TopEnd),
) {
SettingsLayout {
screen()
}
}
@@ -83,6 +83,8 @@
<item name="tile_port_guide_bg">@color/spanish_blue</item>
<item name="tile_port_series_timer_bg">@color/midnight_blue</item>
<item name="tile_port_time_bg">@color/spanish_blue</item>
<item name="android:dialogTheme">@style/Theme.Jellyfin.Dialog</item>
</style>
<style name="Theme.Jellyfin.Preferences" parent="Theme.Jellyfin">
@@ -90,4 +92,9 @@
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowAnimationStyle">@style/WindowAnimation.SlideRight</item>
</style>
<style name="Theme.Jellyfin.Dialog" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowAnimationStyle">@null</item>
</style>
</resources>