20
20
21
21
import static android .view .View .NO_ID ;
22
22
23
+ import android .os .Build .VERSION_CODES ;
23
24
import android .os .Bundle ;
24
25
import androidx .appcompat .app .AppCompatActivity ;
25
26
import androidx .appcompat .widget .Toolbar ;
30
31
import android .view .ViewGroup ;
31
32
import android .widget .Button ;
32
33
import android .widget .TextView ;
34
+ import android .window .BackEvent ;
35
+ import androidx .activity .OnBackPressedCallback ;
33
36
import androidx .annotation .GravityInt ;
34
37
import androidx .annotation .IdRes ;
35
38
import androidx .annotation .LayoutRes ;
36
39
import androidx .annotation .NonNull ;
37
40
import androidx .annotation .Nullable ;
41
+ import androidx .annotation .RequiresApi ;
38
42
import androidx .annotation .StringRes ;
39
43
import androidx .annotation .StyleRes ;
40
44
import androidx .coordinatorlayout .widget .CoordinatorLayout .LayoutParams ;
@@ -96,7 +100,8 @@ public View onCreateDemoView(
96
100
view ,
97
101
R .id .standard_side_sheet_container ,
98
102
R .id .show_standard_side_sheet_button ,
99
- R .id .close_icon_button );
103
+ R .id .close_icon_button ,
104
+ /* shouldHandleBack= */ true );
100
105
101
106
setSideSheetCallback (
102
107
standardRightSideSheet , R .id .side_sheet_state_text , R .id .side_sheet_slide_offset_text );
@@ -107,7 +112,8 @@ public View onCreateDemoView(
107
112
view ,
108
113
R .id .standard_detached_side_sheet_container ,
109
114
R .id .show_standard_detached_side_sheet_button ,
110
- R .id .detached_close_icon_button );
115
+ R .id .detached_close_icon_button ,
116
+ /* shouldHandleBack= */ true );
111
117
112
118
setSideSheetCallback (
113
119
detachedStandardSideSheet ,
@@ -120,7 +126,8 @@ public View onCreateDemoView(
120
126
view ,
121
127
R .id .vertically_scrolling_side_sheet_container ,
122
128
R .id .show_vertically_scrolling_side_sheet_button ,
123
- R .id .vertically_scrolling_side_sheet_close_icon_button );
129
+ R .id .vertically_scrolling_side_sheet_close_icon_button ,
130
+ /* shouldHandleBack= */ true );
124
131
125
132
setSideSheetCallback (
126
133
verticallyScrollingSideSheet ,
@@ -141,7 +148,8 @@ public View onCreateDemoView(
141
148
view ,
142
149
R .id .coplanar_side_sheet_container ,
143
150
R .id .show_coplanar_side_sheet_button ,
144
- R .id .coplanar_side_sheet_close_icon_button );
151
+ R .id .coplanar_side_sheet_close_icon_button ,
152
+ /* shouldHandleBack= */ false );
145
153
146
154
setSideSheetCallback (
147
155
coplanarSideSheet ,
@@ -154,7 +162,8 @@ public View onCreateDemoView(
154
162
view ,
155
163
R .id .coplanar_detached_side_sheet_container ,
156
164
R .id .show_coplanar_detached_side_sheet_button ,
157
- R .id .coplanar_detached_side_sheet_close_icon_button );
165
+ R .id .coplanar_detached_side_sheet_close_icon_button ,
166
+ /* shouldHandleBack= */ false );
158
167
159
168
setSideSheetCallback (
160
169
detachedCoplanarSideSheet ,
@@ -165,8 +174,7 @@ public View onCreateDemoView(
165
174
}
166
175
167
176
private void setUpSheetGravityButtonToggleGroup (@ NonNull View view ) {
168
- sheetGravityButtonToggleGroup =
169
- view .findViewById (R .id .sheet_gravity_button_toggle_group );
177
+ sheetGravityButtonToggleGroup = view .findViewById (R .id .sheet_gravity_button_toggle_group );
170
178
// Check the button corresponding to end sheet gravity, which is the default.
171
179
sheetGravityButtonToggleGroup .check (R .id .end_gravity_button );
172
180
sheetGravityButtonToggleGroup .addOnButtonCheckedListener (
@@ -185,11 +193,39 @@ private void setUpSheetGravityButtonToggleGroup(@NonNull View view) {
185
193
});
186
194
}
187
195
196
+ private void setupBackHandling (SideSheetBehavior <View > sideSheetBehavior ) {
197
+ OnBackPressedCallback nonModalOnBackPressedCallback =
198
+ createNonModalOnBackPressedCallback (sideSheetBehavior );
199
+ requireActivity ().getOnBackPressedDispatcher ().addCallback (this , nonModalOnBackPressedCallback );
200
+ sideSheetBehavior .addCallback (
201
+ new SideSheetCallback () {
202
+ @ Override
203
+ public void onStateChanged (@ NonNull View sheet , int newState ) {
204
+ switch (newState ) {
205
+ case SideSheetBehavior .STATE_EXPANDED :
206
+ case SideSheetBehavior .STATE_SETTLING :
207
+ nonModalOnBackPressedCallback .setEnabled (true );
208
+ break ;
209
+ case SideSheetBehavior .STATE_HIDDEN :
210
+ nonModalOnBackPressedCallback .setEnabled (false );
211
+ break ;
212
+ case SideSheetBehavior .STATE_DRAGGING :
213
+ default :
214
+ break ;
215
+ }
216
+ }
217
+
218
+ @ Override
219
+ public void onSlide (@ NonNull View sheet , float slideOffset ) {}
220
+ });
221
+ }
222
+
188
223
private View setUpSideSheet (
189
224
@ NonNull View view ,
190
225
@ IdRes int sideSheetContainerId ,
191
226
@ IdRes int showSideSheetButtonId ,
192
- @ IdRes int closeIconButtonId ) {
227
+ @ IdRes int closeIconButtonId ,
228
+ boolean shouldHandleBack ) {
193
229
View sideSheet = view .findViewById (sideSheetContainerId );
194
230
SideSheetBehavior <View > sideSheetBehavior = SideSheetBehavior .from (sideSheet );
195
231
@@ -199,6 +235,10 @@ private View setUpSideSheet(
199
235
View standardSideSheetCloseIconButton = sideSheet .findViewById (closeIconButtonId );
200
236
standardSideSheetCloseIconButton .setOnClickListener (v -> hideSideSheet (sideSheetBehavior ));
201
237
238
+ if (shouldHandleBack ) {
239
+ setupBackHandling (sideSheetBehavior );
240
+ }
241
+
202
242
sideSheetViews .add (sideSheet );
203
243
204
244
return sideSheet ;
@@ -258,37 +298,39 @@ private void setUpModalSheet(
258
298
@ StringRes int sheetTitleStringRes ,
259
299
@ NonNull Button showSheetButton ,
260
300
@ IdRes int closeIconButtonIdRes ) {
261
- showSheetButton .setOnClickListener (v1 -> {
262
- SideSheetDialog sheetDialog =
263
- sheetThemeOverlayRes == NO_ID
264
- ? new SideSheetDialog (requireContext ())
265
- : new SideSheetDialog (requireContext (), sheetThemeOverlayRes );
266
-
267
- sheetDialog .setContentView (sheetContentLayoutRes );
268
- View modalSheetContent = sheetDialog .findViewById (sheetContentRootIdRes );
269
- if (modalSheetContent != null ) {
270
- TextView modalSideSheetTitle = modalSheetContent .findViewById (sheetTitleIdRes );
271
- modalSideSheetTitle .setText (sheetTitleStringRes );
272
- }
273
- new WindowPreferencesManager (requireContext ())
274
- .applyEdgeToEdgePreference (sheetDialog .getWindow ());
275
-
276
- sheetDialog
277
- .getBehavior ()
278
- .addCallback (
279
- createSideSheetCallback (
280
- sheetDialog .findViewById (R .id .side_sheet_state_text ),
281
- sheetDialog .findViewById (R .id .side_sheet_slide_offset_text )));
282
-
283
- sheetDialog .setSheetEdge (getGravityForIdRes (sheetGravityButtonToggleGroup .getCheckedButtonId ()));
284
-
285
- View modalSideSheetCloseIconButton = sheetDialog .findViewById (closeIconButtonIdRes );
286
- if (modalSideSheetCloseIconButton != null ) {
287
- modalSideSheetCloseIconButton .setOnClickListener (v2 -> sheetDialog .hide ());
288
- }
301
+ showSheetButton .setOnClickListener (
302
+ v1 -> {
303
+ SideSheetDialog sheetDialog =
304
+ sheetThemeOverlayRes == NO_ID
305
+ ? new SideSheetDialog (requireContext ())
306
+ : new SideSheetDialog (requireContext (), sheetThemeOverlayRes );
307
+
308
+ sheetDialog .setContentView (sheetContentLayoutRes );
309
+ View modalSheetContent = sheetDialog .findViewById (sheetContentRootIdRes );
310
+ if (modalSheetContent != null ) {
311
+ TextView modalSideSheetTitle = modalSheetContent .findViewById (sheetTitleIdRes );
312
+ modalSideSheetTitle .setText (sheetTitleStringRes );
313
+ }
314
+ new WindowPreferencesManager (requireContext ())
315
+ .applyEdgeToEdgePreference (sheetDialog .getWindow ());
316
+
317
+ sheetDialog
318
+ .getBehavior ()
319
+ .addCallback (
320
+ createSideSheetCallback (
321
+ sheetDialog .findViewById (R .id .side_sheet_state_text ),
322
+ sheetDialog .findViewById (R .id .side_sheet_slide_offset_text )));
323
+
324
+ sheetDialog .setSheetEdge (
325
+ getGravityForIdRes (sheetGravityButtonToggleGroup .getCheckedButtonId ()));
326
+
327
+ View modalSideSheetCloseIconButton = sheetDialog .findViewById (closeIconButtonIdRes );
328
+ if (modalSideSheetCloseIconButton != null ) {
329
+ modalSideSheetCloseIconButton .setOnClickListener (v2 -> sheetDialog .hide ());
330
+ }
289
331
290
- sheetDialog .show ();
291
- });
332
+ sheetDialog .show ();
333
+ });
292
334
}
293
335
294
336
private void setUpToolbar (@ NonNull View view ) {
@@ -364,4 +406,32 @@ public void onSlide(@NonNull View sheet, float slideOffset) {
364
406
}
365
407
};
366
408
}
409
+
410
+ private OnBackPressedCallback createNonModalOnBackPressedCallback (
411
+ SideSheetBehavior <View > behavior ) {
412
+ return new OnBackPressedCallback (/* enabled= */ false ) {
413
+ @ RequiresApi (VERSION_CODES .UPSIDE_DOWN_CAKE )
414
+ @ Override
415
+ public void handleOnBackStarted (@ NonNull BackEvent backEvent ) {
416
+ behavior .startBackProgress (backEvent );
417
+ }
418
+
419
+ @ RequiresApi (VERSION_CODES .UPSIDE_DOWN_CAKE )
420
+ @ Override
421
+ public void handleOnBackProgressed (@ NonNull BackEvent backEvent ) {
422
+ behavior .updateBackProgress (backEvent );
423
+ }
424
+
425
+ @ Override
426
+ public void handleOnBackPressed () {
427
+ behavior .handleBackInvoked ();
428
+ }
429
+
430
+ @ RequiresApi (VERSION_CODES .UPSIDE_DOWN_CAKE )
431
+ @ Override
432
+ public void handleOnBackCancelled () {
433
+ behavior .cancelBackProgress ();
434
+ }
435
+ };
436
+ }
367
437
}
0 commit comments