1+ package com.getcode.navigation.scrim
2+
3+ import androidx.compose.animation.AnimatedContent
4+ import androidx.compose.animation.AnimatedVisibility
5+ import androidx.compose.animation.EnterTransition
6+ import androidx.compose.animation.ExitTransition
7+ import androidx.compose.animation.fadeIn
8+ import androidx.compose.animation.fadeOut
9+ import androidx.compose.animation.togetherWith
10+ import androidx.compose.foundation.background
11+ import androidx.compose.foundation.layout.Box
12+ import androidx.compose.foundation.layout.Spacer
13+ import androidx.compose.foundation.layout.fillMaxSize
14+ import androidx.compose.foundation.layout.fillMaxWidth
15+ import androidx.compose.runtime.Composable
16+ import androidx.compose.runtime.getValue
17+ import androidx.compose.runtime.mutableStateOf
18+ import androidx.compose.runtime.setValue
19+ import androidx.compose.runtime.staticCompositionLocalOf
20+ import androidx.compose.ui.Alignment
21+ import androidx.compose.ui.Modifier
22+ import com.getcode.theme.CodeTheme
23+ import com.getcode.ui.core.noRippleClickable
24+
25+ class ScrimController {
26+ var visible by mutableStateOf(false )
27+ private set
28+
29+ private var onDismiss: (() -> Unit )? = null
30+ var overlayAlignment: Alignment by mutableStateOf(Alignment .Center )
31+ private set
32+ var overlayContent: (@Composable () -> Unit )? by mutableStateOf(null )
33+ private set
34+ var enterTransition: EnterTransition by mutableStateOf(fadeIn())
35+ private set
36+ var exitTransition: ExitTransition by mutableStateOf(fadeOut())
37+ private set
38+
39+
40+ fun show (
41+ content : (@Composable () -> Unit )? = null,
42+ enterTransition : EnterTransition = fadeIn(),
43+ exitTransition : ExitTransition = fadeOut(),
44+ alignment : Alignment = Alignment .Center ,
45+ onDismiss : () -> Unit ,
46+ ) {
47+ this .onDismiss = onDismiss
48+ this .overlayContent = content
49+ this .overlayAlignment = alignment
50+ this .enterTransition = enterTransition
51+ this .exitTransition = exitTransition
52+ visible = true
53+ }
54+
55+ private fun hide () {
56+ visible = false
57+ onDismiss = null
58+ overlayContent = null
59+
60+ }
61+
62+ fun dismiss () {
63+ onDismiss?.invoke()
64+ hide()
65+ }
66+ }
67+
68+ val LocalScrimController = staticCompositionLocalOf<ScrimController > {
69+ error(" No ScrimController provided" )
70+ }
71+
72+ @Composable
73+ fun ScrimOverlay (controller : ScrimController ) {
74+ Box (modifier = Modifier .fillMaxSize()) {
75+ AnimatedVisibility (
76+ visible = controller.visible,
77+ enter = fadeIn(),
78+ exit = fadeOut(),
79+ ) {
80+ Box (
81+ modifier = Modifier
82+ .fillMaxSize()
83+ .background(CodeTheme .colors.scrim)
84+ .noRippleClickable { controller.dismiss() },
85+ )
86+ }
87+
88+ AnimatedContent (
89+ modifier = Modifier .align(controller.overlayAlignment),
90+ targetState = controller.overlayContent,
91+ transitionSpec = {
92+ controller.enterTransition togetherWith controller.exitTransition
93+ }
94+ ) { content ->
95+ if (content != null ) {
96+ content()
97+ } else {
98+ Spacer (Modifier .fillMaxWidth())
99+ }
100+ }
101+ }
102+ }
0 commit comments