Add ReduceMotion support for Dialogs, Confirmations and OpenOnPhoneDialog
Bug: 378683095
Test: Manually verified
Change-Id: I2b2ab0f13743453e04aea5f1c21c21a05929af46
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimationSpecUtils.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimationSpecUtils.kt
index ef59b1a..2a17737 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimationSpecUtils.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/AnimationSpecUtils.kt
@@ -28,6 +28,7 @@
import androidx.compose.animation.core.TwoWayConverter
import androidx.compose.animation.core.VectorizedAnimationSpec
import androidx.compose.runtime.withFrameMillis
+import kotlinx.coroutines.delay
/**
* Returns a new [AnimationSpec] that is a faster version of this one.
@@ -169,4 +170,11 @@
return
}
+/** Delay to be used for animations. Will enable delay only when ReducedMotion is disabled. */
+internal suspend fun animatedDelay(duration: Long, reduceMotionEnabled: Boolean) {
+ if (!reduceMotionEnabled) {
+ delay(duration)
+ }
+}
+
private const val MAX_WAIT_TIME_MILLIS = 1_000L
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Confirmation.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Confirmation.kt
index 6bfc308..310e831 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Confirmation.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Confirmation.kt
@@ -61,6 +61,7 @@
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedScope
import androidx.wear.compose.foundation.CurvedTextStyle
+import androidx.wear.compose.foundation.LocalReduceMotion
import androidx.wear.compose.foundation.padding
import androidx.wear.compose.material3.tokens.ColorSchemeKeyTokens
import androidx.wear.compose.material3.tokens.MotionTokens.DurationShort2
@@ -191,6 +192,7 @@
}
}
+ val reduceMotionEnabled = LocalReduceMotion.current.enabled()
Dialog(
show = show,
modifier = modifier,
@@ -200,7 +202,7 @@
val alphaAnimatable = remember { Animatable(0f) }
val textOpacityAnimationSpec = TextOpacityAnimationSpec
LaunchedEffect(Unit) {
- delay(DurationShort2.toLong())
+ animatedDelay(DurationShort2.toLong(), reduceMotionEnabled)
alphaAnimatable.animateTo(1f, textOpacityAnimationSpec)
}
@@ -353,8 +355,10 @@
durationMillis = durationMillis,
) {
val translationXAnimatable = remember { Animatable(FailureContentTransition[0]) }
+ val reduceMotionEnabled = LocalReduceMotion.current.enabled()
+
LaunchedEffect(Unit) {
- delay(DurationShort3.toLong())
+ animatedDelay(DurationShort3.toLong(), reduceMotionEnabled)
translationXAnimatable.animateTo(
FailureContentTransition[1],
FailureContentAnimationSpecs[0]
@@ -405,8 +409,10 @@
val animation =
AnimatedImageVector.animatedVectorResource(R.drawable.wear_m3c_check_animation)
var atEnd by remember { mutableStateOf(false) }
+ val reduceMotionEnabled = LocalReduceMotion.current.enabled()
+
LaunchedEffect(Unit) {
- delay(IconDelay)
+ animatedDelay(IconDelay, reduceMotionEnabled)
atEnd = true
}
Icon(
@@ -425,8 +431,10 @@
val animation =
AnimatedImageVector.animatedVectorResource(R.drawable.wear_m3c_failure_animation)
var atEnd by remember { mutableStateOf(false) }
+ val reduceMotionEnabled = LocalReduceMotion.current.enabled()
+
LaunchedEffect(Unit) {
- delay(IconDelay)
+ animatedDelay(IconDelay, reduceMotionEnabled)
atEnd = true
}
Icon(
@@ -662,8 +670,10 @@
) {
val alphaAnimatable = remember { Animatable(0f) }
val textOpacityAnimationSpec = TextOpacityAnimationSpec
+ val reduceMotionEnabled = LocalReduceMotion.current.enabled()
+
LaunchedEffect(Unit) {
- delay(DurationShort2.toLong())
+ animatedDelay(DurationShort2.toLong(), reduceMotionEnabled)
alphaAnimatable.animateTo(1f, textOpacityAnimationSpec)
}
Box(modifier = Modifier.fillMaxSize()) {
@@ -705,8 +715,10 @@
MaterialTheme.motionScheme.defaultSpatialSpec()
val heroShapeRotationAnimationSpec: AnimationSpec<Float> =
MaterialTheme.motionScheme.slowEffectsSpec()
+ val reduceMotionEnabled = LocalReduceMotion.current.enabled()
+
LaunchedEffect(Unit) {
- delay(DurationShort2.toLong())
+ animatedDelay(DurationShort2.toLong(), reduceMotionEnabled)
launch { shapeAnimatable.animateTo(1f, heroShapeMorphAnimationSpec) }
rotateAnimatable.animateTo(0f, heroShapeRotationAnimationSpec)
}
@@ -728,9 +740,10 @@
val targetHeight = screenHeightDp() * SuccessHeightFraction.toFloat()
val heightAnimatable = remember { Animatable(width) }
+ val reduceMotionEnabled = LocalReduceMotion.current.enabled()
LaunchedEffect(Unit) {
- delay(DurationShort2.toLong())
+ animatedDelay(DurationShort2.toLong(), reduceMotionEnabled)
heightAnimatable.animateTo(targetHeight, SuccessContainerAnimationSpec)
}
Box(
@@ -756,8 +769,10 @@
}
val failureContainerAnimationSpec: AnimationSpec<Float> =
MaterialTheme.motionScheme.fastEffectsSpec()
+ val reduceMotionEnabled = LocalReduceMotion.current.enabled()
+
LaunchedEffect(Unit) {
- delay(DurationShort2.toLong())
+ animatedDelay(DurationShort2.toLong(), reduceMotionEnabled)
shapeAnimatable.animateTo(1f, failureContainerAnimationSpec)
}
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Dialog.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Dialog.kt
index c49273b..cd6b76d 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Dialog.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Dialog.kt
@@ -38,6 +38,7 @@
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.window.DialogWindowProvider
+import androidx.wear.compose.foundation.LocalReduceMotion
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
import androidx.wear.compose.material3.MotionScheme.Companion.standard
import kotlinx.coroutines.flow.collectLatest
@@ -83,19 +84,23 @@
val backgroundAnimationSpec = MaterialTheme.motionScheme.defaultEffectsSpec<Float>().faster(50f)
- LaunchedEffect(Unit) {
- snapshotFlow { showState }
- .collectLatest {
- if (it) {
- backgroundAnimatable.animateTo(0.85f, backgroundAnimationSpec) {
- scaffoldState.parentScale.floatValue = value
- }
- } else {
- backgroundAnimatable.animateTo(1f, backgroundAnimationSpec) {
- scaffoldState.parentScale.floatValue = value
+ val isReduceMotionEnabled = LocalReduceMotion.current.enabled()
+
+ if (!isReduceMotionEnabled) {
+ LaunchedEffect(Unit) {
+ snapshotFlow { showState }
+ .collectLatest {
+ if (it) {
+ backgroundAnimatable.animateTo(0.85f, backgroundAnimationSpec) {
+ scaffoldState.parentScale.floatValue = value
+ }
+ } else {
+ backgroundAnimatable.animateTo(1f, backgroundAnimationSpec) {
+ scaffoldState.parentScale.floatValue = value
+ }
}
}
- }
+ }
}
if (shouldShow) {
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/OpenOnPhoneDialog.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/OpenOnPhoneDialog.kt
index ea1cd22..6063174 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/OpenOnPhoneDialog.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/OpenOnPhoneDialog.kt
@@ -57,6 +57,7 @@
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedScope
import androidx.wear.compose.foundation.CurvedTextStyle
+import androidx.wear.compose.foundation.LocalReduceMotion
import androidx.wear.compose.foundation.padding
import androidx.wear.compose.material3.tokens.ColorSchemeKeyTokens
import androidx.wear.compose.material3.tokens.MotionTokens.DurationLong2
@@ -135,22 +136,24 @@
val progressDuration = a11yFullDurationMillis - finalAnimationDuration
val alphaAnimationSpec = MaterialTheme.motionScheme.fastEffectsSpec<Float>()
+ val reduceMotionEnabled = LocalReduceMotion.current.enabled()
LaunchedEffect(a11yFullDurationMillis) {
launch {
- delay(DurationShort3.toLong())
+ animatedDelay(DurationShort3.toLong(), reduceMotionEnabled)
alphaAnimatable.animateTo(1f, alphaAnimationSpec)
}
launch {
- progressAnimatable.snapTo(0f)
- progressAnimatable.animateTo(
- targetValue = 1f,
- animationSpec =
- tween(durationMillis = progressDuration.toInt(), easing = LinearEasing),
- ) {
- progress = value
+ if (!reduceMotionEnabled) {
+ progressAnimatable.animateTo(
+ targetValue = 1f,
+ animationSpec =
+ tween(durationMillis = progressDuration.toInt(), easing = LinearEasing),
+ ) {
+ progress = value
+ }
+ finalAnimation = true
}
- finalAnimation = true
}
}
@@ -217,8 +220,10 @@
val animation =
AnimatedImageVector.animatedVectorResource(R.drawable.wear_m3c_open_on_phone_animation)
var atEnd by remember { mutableStateOf(false) }
+ val reduceMotionEnabled = LocalReduceMotion.current.enabled()
+
LaunchedEffect(Unit) {
- delay(IconDelay)
+ animatedDelay(IconDelay, reduceMotionEnabled)
atEnd = true
}
Icon(