@@ -21,24 +21,14 @@ import androidx.compose.runtime.DisposableEffect
2121import androidx.compose.runtime.Immutable
2222import androidx.compose.runtime.InternalComposeApi
2323import androidx.compose.runtime.LaunchedEffect
24- import androidx.compose.runtime.State
2524import androidx.compose.runtime.getValue
26- import androidx.compose.runtime.mutableStateOf
2725import androidx.compose.runtime.remember
28- import androidx.compose.runtime.rememberCompositionContext
2926import androidx.compose.runtime.rememberUpdatedState
30- import androidx.compose.runtime.setValue
31- import androidx.compose.ui.ComposeUiFlags
3227import androidx.compose.ui.Modifier
33- import androidx.compose.ui.MotionDurationScale
34- import androidx.compose.ui.animation.easeOutTimingFunction
35- import androidx.compose.ui.animation.withAnimationProgress
3628import androidx.compose.ui.graphics.BlendMode
3729import androidx.compose.ui.graphics.Color
38- import androidx.compose.ui.graphics.graphicsLayer
3930import androidx.compose.ui.input.pointer.PointerButton
4031import androidx.compose.ui.input.pointer.PointerEventType
41- import androidx.compose.ui.isDialogAnimationEnabled
4232import androidx.compose.ui.layout.Layout
4333import androidx.compose.ui.platform.LocalPlatformWindowInsets
4434import androidx.compose.ui.platform.LocalWindowInfo
@@ -54,25 +44,12 @@ import androidx.compose.ui.semantics.semantics
5444import androidx.compose.ui.unit.IntRect
5545import androidx.compose.ui.unit.IntSize
5646import androidx.compose.ui.unit.center
57- import kotlin.coroutines.CoroutineContext
58- import kotlin.getValue
59- import kotlin.setValue
60- import kotlin.time.Duration.Companion.seconds
61- import kotlinx.coroutines.CoroutineScope
62- import kotlinx.coroutines.CoroutineStart
63- import kotlinx.coroutines.Job
64- import kotlinx.coroutines.launch
6547
6648/* *
6749 * The default scrim opacity.
6850 */
6951private const val DefaultScrimOpacity = 0.6f
7052private val DefaultScrimColor = Color .Black .copy(alpha = DefaultScrimOpacity )
71- private const val AnimatedLayerOffsetDp = 10f
72- private const val AnimatedLayerInitialAlpha = 0.2f
73- private const val AnimatedLayerScale = 0.05f
74- private const val AnimatedLayerAppearanceDuration = 0.2
75- private const val AnimatedLayerDisappearanceDuration = 0.1
7653
7754/* *
7855 * Properties used to customize the behavior of a [Dialog].
@@ -91,7 +68,7 @@ private const val AnimatedLayerDisappearanceDuration = 0.1
9168 * @property scrimColor Color of background fill.
9269 */
9370@Immutable
94- actual class DialogProperties (
71+ actual class DialogProperties constructor (
9572 actual val dismissOnBackPress : Boolean = true ,
9673 actual val dismissOnClickOutside : Boolean = true ,
9774 actual val usePlatformDefaultWidth : Boolean = true ,
@@ -189,20 +166,13 @@ private fun DialogLayout(
189166 content : @Composable () -> Unit
190167) {
191168 val currentContent by rememberUpdatedState(content)
192- val compositionContext = rememberCompositionContext()
193- val layer = rememberComposeSceneLayer(focusable = true )
194- layer.setOutsidePointerEventListener(onOutsidePointerEvent)
195-
196- val animator = remember {
197- DialogAppearanceController (layer = layer, coroutineContext = compositionContext.effectCoroutineContext)
198- }
199- animator.scrimColor = properties.scrimColor
200169
170+ val layer = rememberComposeSceneLayer(
171+ focusable = true
172+ )
173+ layer.scrimColor = properties.scrimColor
174+ layer.setOutsidePointerEventListener(onOutsidePointerEvent)
201175 layer.Content {
202- LaunchedEffect (Unit ) {
203- animator.onDialogShown()
204- }
205-
206176 val platformInsets = properties.platformInsets
207177 val containerSize = LocalWindowInfo .current.containerSize
208178 val measurePolicy = rememberDialogMeasurePolicy(
@@ -218,120 +188,11 @@ private fun DialogLayout(
218188 ) {
219189 Layout (
220190 content = currentContent,
221- modifier = animator. modifier.then(modifier) ,
191+ modifier = modifier,
222192 measurePolicy = measurePolicy
223193 )
224194 }
225195 }
226-
227- DisposableEffect (Unit ) {
228- onDispose {
229- animator.hideDialog()
230- }
231- }
232- }
233-
234- private interface DialogAppearanceController {
235- var scrimColor: Color ?
236- val modifier: Modifier
237- fun onDialogShown ()
238- fun hideDialog ()
239- }
240-
241- private fun DialogAppearanceController (
242- layer : ComposeSceneLayer ,
243- coroutineContext : CoroutineContext
244- ): DialogAppearanceController =
245- if (ComposeUiFlags .isDialogAnimationEnabled) {
246- AnimatedDialogAppearanceController (layer, coroutineContext)
247- } else {
248- NonAnimatedDialogAppearanceController (layer)
249- }
250-
251- private class AnimatedDialogAppearanceController (
252- private val layer : ComposeSceneLayer ,
253- private val coroutineContext : CoroutineContext
254- ) : DialogAppearanceController {
255- private val appearanceProgress = mutableStateOf(0f )
256- private var appearAnimationJob: Job ? = null
257-
258- override var modifier by mutableStateOf(
259- Modifier .animationLayerTransform(appearanceProgress)
260- )
261- private set
262-
263- override var scrimColor: Color ? = Color .Transparent
264- set(value) {
265- field = value
266- updateScrimLayerColor()
267- }
268-
269- override fun onDialogShown () {
270- appearAnimationJob =
271- CoroutineScope (coroutineContext).launch(start = CoroutineStart .UNDISPATCHED ) {
272- withAnimationProgress(
273- duration = (durationScale() * AnimatedLayerAppearanceDuration ).seconds,
274- timingFunction = ::easeOutTimingFunction
275- ) { progress ->
276- appearanceProgress.value = progress
277- updateScrimLayerColor()
278- }
279-
280- modifier = Modifier
281- layer.scrimColor = scrimColor
282- }
283- }
284-
285- override fun hideDialog () {
286- appearAnimationJob?.cancel()
287- CoroutineScope (coroutineContext).launch(start = CoroutineStart .UNDISPATCHED ) {
288- val initialProgress = appearanceProgress.value
289- val duration =
290- durationScale() * initialProgress * AnimatedLayerDisappearanceDuration
291- modifier = Modifier .animationLayerTransform(appearanceProgress)
292-
293- withAnimationProgress(
294- duration = duration.seconds,
295- timingFunction = ::easeOutTimingFunction
296- ) { progress ->
297- appearanceProgress.value = (1f - progress) * initialProgress
298- updateScrimLayerColor()
299- }
300-
301- layer.close()
302- }
303- }
304-
305- private fun updateScrimLayerColor () {
306- layer.scrimColor = scrimColor?.let {
307- it.copy(it.alpha * contentAlpha(appearanceProgress.value))
308- }
309- }
310-
311- private fun contentAlpha (progress : Float ): Float =
312- AnimatedLayerInitialAlpha + (1f - AnimatedLayerInitialAlpha ) * progress
313-
314- private fun durationScale (): Float =
315- coroutineContext[MotionDurationScale ]?.scaleFactor ? : 1f
316-
317- private fun Modifier.animationLayerTransform (progress : State <Float >): Modifier =
318- graphicsLayer {
319- this .alpha = contentAlpha(progress.value)
320- val reversedProgress = 1f - progress.value
321- val scale = 1f - reversedProgress * AnimatedLayerScale
322- this .scaleX = scale
323- this .scaleY = scale
324- this .translationY = AnimatedLayerOffsetDp * reversedProgress * density
325- }
326- }
327-
328- private class NonAnimatedDialogAppearanceController (
329- private val layer : ComposeSceneLayer
330- ) : DialogAppearanceController {
331- override var scrimColor: Color ? by layer::scrimColor
332- override fun onDialogShown () {}
333- override fun hideDialog () = layer.close()
334- override val modifier = Modifier
335196}
336197
337198private val DialogProperties .platformInsets: PlatformInsets
0 commit comments