@@ -61,7 +61,7 @@ internal fun ModalSheetDialog(
61
61
val currentContent by rememberUpdatedState(content)
62
62
val dialogId = rememberSaveable { UUID .randomUUID() }
63
63
val dialog = remember(view, density) {
64
- ModalSheetDialogLayout . ModalSheetDialogWrapper (
64
+ ModalSheetDialogWrapper (
65
65
onPredictiveBack,
66
66
view,
67
67
securePolicy,
@@ -120,132 +120,128 @@ private class ModalSheetDialogLayout(
120
120
PredictiveBackHandler { onPredictiveBack(it) }
121
121
content()
122
122
}
123
+ }
123
124
124
- // Fork of androidx.compose.ui.window.DialogWrapper.
125
- // predictiveBackProgress and scope params added for predictive back implementation.
126
- // EdgeToEdgeFloatingDialogWindowTheme provided to allow theme to extend into status bar.
127
- class ModalSheetDialogWrapper (
128
- private var onPredictiveBack : suspend (Flow <BackEventCompat >) -> Unit ,
129
- private val composeView : View ,
130
- securePolicy : SecureFlagPolicy ,
131
- layoutDirection : LayoutDirection ,
132
- density : Density ,
133
- dialogId : UUID ,
134
- ) : ComponentDialog(
135
- ContextThemeWrapper (
136
- composeView.context,
137
- R .style.EdgeToEdgeFloatingDialogWindowTheme ,
138
- ),
139
- ), ViewRootForInspector {
140
- private val dialogLayout: ModalSheetDialogLayout
125
+ // Fork of androidx.compose.ui.window.DialogWrapper.
126
+ // predictiveBackProgress and scope params added for predictive back implementation.
127
+ // EdgeToEdgeFloatingDialogWindowTheme provided to allow theme to extend into status bar.
128
+ internal class ModalSheetDialogWrapper (
129
+ private var onPredictiveBack : suspend (Flow <BackEventCompat >) -> Unit ,
130
+ private val composeView : View ,
131
+ securePolicy : SecureFlagPolicy ,
132
+ layoutDirection : LayoutDirection ,
133
+ density : Density ,
134
+ dialogId : UUID ,
135
+ ) : ComponentDialog(ContextThemeWrapper (composeView.context, R .style.EdgeToEdgeFloatingDialogWindowTheme )),
136
+ ViewRootForInspector {
137
+ private val dialogLayout: ModalSheetDialogLayout
141
138
142
- // On systems older than Android S, there is a bug in the surface insets matrix math used by
143
- // elevation, so high values of maxSupportedElevation break accessibility services: b/232788477.
144
- private val maxSupportedElevation = 8 .dp
145
- override val subCompositionView: AbstractComposeView get() = dialogLayout
139
+ // On systems older than Android S, there is a bug in the surface insets matrix math used by
140
+ // elevation, so high values of maxSupportedElevation break accessibility services: b/232788477.
141
+ private val maxSupportedElevation = 8 .dp
142
+ override val subCompositionView: AbstractComposeView get() = dialogLayout
146
143
147
- init {
148
- val window = window ? : error(" Dialog has no window" )
149
- window.requestFeature(Window .FEATURE_NO_TITLE )
150
- window.setBackgroundDrawableResource(android.R .color.transparent)
151
- WindowCompat .setDecorFitsSystemWindows(window, false )
152
- dialogLayout = ModalSheetDialogLayout (
153
- context,
154
- window,
155
- onPredictiveBack,
156
- ).apply {
157
- // Set unique id for AbstractComposeView. This allows state restoration for the state
158
- // defined inside the Dialog via rememberSaveable()
159
- setTag(R .id.compose_view_saveable_id_tag, " Dialog:$dialogId " )
160
- // Enable children to draw their shadow by not clipping them
161
- clipChildren = false
162
- // Allocate space for elevation
163
- with (density) { elevation = maxSupportedElevation.toPx() }
164
- // Simple outline to force window manager to allocate space for shadow.
165
- // Note that the outline affects clickable area for the dismiss listener. In case of
166
- // shapes like circle the area for dismiss might be to small (rectangular outline
167
- // consuming clicks outside of the circle).
168
- outlineProvider = object : ViewOutlineProvider () {
169
- override fun getOutline (view : View , result : Outline ) {
170
- result.setRect(0 , 0 , view.width, view.height)
171
- // We set alpha to 0 to hide the view's shadow and let the composable to draw
172
- // its own shadow. This still enables us to get the extra space needed in the
173
- // surface.
174
- result.alpha = 0f
175
- }
144
+ init {
145
+ val window = window ? : error(" Dialog has no window" )
146
+ window.requestFeature(Window .FEATURE_NO_TITLE )
147
+ window.setBackgroundDrawableResource(android.R .color.transparent)
148
+ WindowCompat .setDecorFitsSystemWindows(window, false )
149
+ dialogLayout = ModalSheetDialogLayout (
150
+ context,
151
+ window,
152
+ onPredictiveBack,
153
+ ).apply {
154
+ // Set unique id for AbstractComposeView. This allows state restoration for the state
155
+ // defined inside the Dialog via rememberSaveable()
156
+ setTag(R .id.compose_view_saveable_id_tag, " Dialog:$dialogId " )
157
+ // Enable children to draw their shadow by not clipping them
158
+ clipChildren = false
159
+ // Allocate space for elevation
160
+ with (density) { elevation = maxSupportedElevation.toPx() }
161
+ // Simple outline to force window manager to allocate space for shadow.
162
+ // Note that the outline affects clickable area for the dismiss listener. In case of
163
+ // shapes like circle the area for dismiss might be to small (rectangular outline
164
+ // consuming clicks outside of the circle).
165
+ outlineProvider = object : ViewOutlineProvider () {
166
+ override fun getOutline (view : View , result : Outline ) {
167
+ result.setRect(0 , 0 , view.width, view.height)
168
+ // We set alpha to 0 to hide the view's shadow and let the composable to draw
169
+ // its own shadow. This still enables us to get the extra space needed in the
170
+ // surface.
171
+ result.alpha = 0f
176
172
}
177
173
}
178
- // Clipping logic removed because we are spanning edge to edge.
179
- setContentView(dialogLayout)
180
- dialogLayout.setViewTreeLifecycleOwner(composeView.findViewTreeLifecycleOwner())
181
- dialogLayout.setViewTreeViewModelStoreOwner(composeView.findViewTreeViewModelStoreOwner())
182
- dialogLayout.setViewTreeSavedStateRegistryOwner(
183
- composeView.findViewTreeSavedStateRegistryOwner(),
184
- )
185
- dialogLayout.setViewTreeOnBackPressedDispatcherOwner(this )
186
- // Initial setup
187
- updateParameters(onPredictiveBack, securePolicy, layoutDirection)
188
- WindowCompat .getInsetsController(window, window.decorView).apply {
189
- isAppearanceLightStatusBars = true
190
- isAppearanceLightNavigationBars = true
191
- }
192
174
}
193
-
194
- private fun setLayoutDirection (layoutDirection : LayoutDirection ) {
195
- dialogLayout.layoutDirection = when (layoutDirection) {
196
- LayoutDirection .Ltr -> android.util.LayoutDirection .LTR
197
- LayoutDirection .Rtl -> android.util.LayoutDirection .RTL
198
- }
175
+ // Clipping logic removed because we are spanning edge to edge.
176
+ setContentView(dialogLayout)
177
+ dialogLayout.setViewTreeLifecycleOwner(composeView.findViewTreeLifecycleOwner())
178
+ dialogLayout.setViewTreeViewModelStoreOwner(composeView.findViewTreeViewModelStoreOwner())
179
+ dialogLayout.setViewTreeSavedStateRegistryOwner(
180
+ composeView.findViewTreeSavedStateRegistryOwner(),
181
+ )
182
+ dialogLayout.setViewTreeOnBackPressedDispatcherOwner(this )
183
+ // Initial setup
184
+ updateParameters(onPredictiveBack, securePolicy, layoutDirection)
185
+ WindowCompat .getInsetsController(window, window.decorView).apply {
186
+ isAppearanceLightStatusBars = true
187
+ isAppearanceLightNavigationBars = true
199
188
}
189
+ }
200
190
201
- fun setContent (parentComposition : CompositionContext , children : @Composable () -> Unit ) {
202
- dialogLayout.setContent(parentComposition, children)
191
+ private fun setLayoutDirection (layoutDirection : LayoutDirection ) {
192
+ dialogLayout.layoutDirection = when (layoutDirection) {
193
+ LayoutDirection .Ltr -> android.util.LayoutDirection .LTR
194
+ LayoutDirection .Rtl -> android.util.LayoutDirection .RTL
203
195
}
196
+ }
204
197
205
- private fun setSecurePolicy (securePolicy : SecureFlagPolicy ) {
206
- val secureFlagEnabled =
207
- securePolicy.shouldApplySecureFlag(composeView.isFlagSecureEnabled())
208
- window!! .setFlags(
209
- if (secureFlagEnabled) {
210
- WindowManager .LayoutParams .FLAG_SECURE
211
- } else {
212
- WindowManager .LayoutParams .FLAG_SECURE .inv ()
213
- },
214
- WindowManager .LayoutParams .FLAG_SECURE ,
215
- )
216
- }
198
+ fun setContent (parentComposition : CompositionContext , children : @Composable () -> Unit ) {
199
+ dialogLayout.setContent(parentComposition, children)
200
+ }
217
201
218
- fun updateParameters (
219
- onPredictiveBack : suspend (Flow <BackEventCompat >) -> Unit ,
220
- securePolicy : SecureFlagPolicy ,
221
- layoutDirection : LayoutDirection ,
222
- ) {
223
- this .onPredictiveBack = onPredictiveBack
224
- setSecurePolicy(securePolicy)
225
- setLayoutDirection(layoutDirection)
226
- // Window flags to span parent window.
227
- window?.setLayout(
228
- WindowManager .LayoutParams .MATCH_PARENT ,
229
- WindowManager .LayoutParams .MATCH_PARENT ,
230
- )
231
- window?.setSoftInputMode(
232
- if (Build .VERSION .SDK_INT >= 30 ) {
233
- WindowManager .LayoutParams .SOFT_INPUT_ADJUST_NOTHING
234
- } else {
235
- @Suppress(" DEPRECATION" )
236
- WindowManager .LayoutParams .SOFT_INPUT_ADJUST_RESIZE
237
- },
238
- )
239
- }
202
+ private fun setSecurePolicy (securePolicy : SecureFlagPolicy ) {
203
+ val secureFlagEnabled =
204
+ securePolicy.shouldApplySecureFlag(composeView.isFlagSecureEnabled())
205
+ window!! .setFlags(
206
+ if (secureFlagEnabled) {
207
+ WindowManager .LayoutParams .FLAG_SECURE
208
+ } else {
209
+ WindowManager .LayoutParams .FLAG_SECURE .inv ()
210
+ },
211
+ WindowManager .LayoutParams .FLAG_SECURE ,
212
+ )
213
+ }
240
214
241
- fun disposeComposition () {
242
- dialogLayout.disposeComposition()
243
- }
215
+ fun updateParameters (
216
+ onPredictiveBack : suspend (Flow <BackEventCompat >) -> Unit ,
217
+ securePolicy : SecureFlagPolicy ,
218
+ layoutDirection : LayoutDirection ,
219
+ ) {
220
+ this .onPredictiveBack = onPredictiveBack
221
+ setSecurePolicy(securePolicy)
222
+ setLayoutDirection(layoutDirection)
223
+ // Window flags to span parent window.
224
+ window?.setLayout(
225
+ WindowManager .LayoutParams .MATCH_PARENT ,
226
+ WindowManager .LayoutParams .MATCH_PARENT ,
227
+ )
228
+ window?.setSoftInputMode(
229
+ if (Build .VERSION .SDK_INT >= 30 ) {
230
+ WindowManager .LayoutParams .SOFT_INPUT_ADJUST_NOTHING
231
+ } else {
232
+ @Suppress(" DEPRECATION" )
233
+ WindowManager .LayoutParams .SOFT_INPUT_ADJUST_RESIZE
234
+ },
235
+ )
236
+ }
244
237
245
- override fun cancel () {
246
- // Prevents the dialog from dismissing itself
247
- return
248
- }
238
+ fun disposeComposition () {
239
+ dialogLayout.disposeComposition()
240
+ }
241
+
242
+ override fun cancel () {
243
+ // Prevents the dialog from dismissing itself
244
+ return
249
245
}
250
246
}
251
247
0 commit comments