68
68
import androidx .annotation .LayoutRes ;
69
69
import androidx .annotation .NonNull ;
70
70
import androidx .annotation .Nullable ;
71
- import androidx .annotation .RequiresApi ;
72
71
import androidx .annotation .RestrictTo ;
73
72
import androidx .coordinatorlayout .widget .CoordinatorLayout ;
74
73
import androidx .core .graphics .drawable .DrawableCompat ;
@@ -284,49 +283,11 @@ public boolean handleMessage(@NonNull Message message) {
284
283
285
284
private boolean anchorViewLayoutListenerEnabled = false ;
286
285
287
- @ RequiresApi (VERSION_CODES .Q )
288
- private final Runnable bottomMarginGestureInsetRunnable =
289
- new Runnable () {
290
- @ Override
291
- public void run () {
292
- if (view == null || context == null ) {
293
- return ;
294
- }
295
- // Calculate current bottom inset, factoring in translationY to account for where the
296
- // view will likely be animating to.
297
- int screenHeight = WindowUtils .getCurrentWindowBounds (context ).height ();
298
- int currentInsetBottom =
299
- screenHeight - getViewAbsoluteBottom () + (int ) view .getTranslationY ();
300
- if (currentInsetBottom >= extraBottomMarginGestureInset ) {
301
- // No need to add extra offset if view is already outside of bottom gesture area
302
- appliedBottomMarginGestureInset = extraBottomMarginGestureInset ;
303
- return ;
304
- }
305
-
306
- LayoutParams layoutParams = view .getLayoutParams ();
307
- if (!(layoutParams instanceof MarginLayoutParams )) {
308
- Log .w (
309
- TAG ,
310
- "Unable to apply gesture inset because layout params are not MarginLayoutParams" );
311
- return ;
312
- }
313
-
314
- appliedBottomMarginGestureInset = extraBottomMarginGestureInset ;
315
-
316
- // Move view outside of bottom gesture area
317
- MarginLayoutParams marginParams = (MarginLayoutParams ) layoutParams ;
318
- marginParams .bottomMargin += extraBottomMarginGestureInset - currentInsetBottom ;
319
- view .requestLayout ();
320
- }
321
- };
322
-
323
286
private int extraBottomMarginWindowInset ;
324
287
private int extraLeftMarginWindowInset ;
325
288
private int extraRightMarginWindowInset ;
326
- private int extraBottomMarginAnchorView ;
327
289
328
290
private int extraBottomMarginGestureInset ;
329
- private int appliedBottomMarginGestureInset ;
330
291
331
292
private boolean pendingShowingView ;
332
293
@@ -476,39 +437,45 @@ private void updateMargins() {
476
437
return ;
477
438
}
478
439
479
- int extraBottomMargin =
480
- getAnchorView () != null ? extraBottomMarginAnchorView : extraBottomMarginWindowInset ;
481
-
482
440
MarginLayoutParams marginParams = (MarginLayoutParams ) layoutParams ;
483
- int newBottomMargin = view .originalMargins .bottom + extraBottomMargin ;
484
- int newLeftMargin = view .originalMargins .left + extraLeftMarginWindowInset ;
485
- int newRightMargin = view .originalMargins .right + extraRightMarginWindowInset ;
486
- int newTopMargin = view .originalMargins .top ;
487
441
488
- boolean marginChanged =
442
+ final int newBottomMargin = view .originalMargins .bottom + calculateExtraBottomMargin ();
443
+ final int newLeftMargin = view .originalMargins .left + extraLeftMarginWindowInset ;
444
+ final int newRightMargin = view .originalMargins .right + extraRightMarginWindowInset ;
445
+ final int newTopMargin = view .originalMargins .top ;
446
+
447
+ final boolean marginChanged =
489
448
marginParams .bottomMargin != newBottomMargin
490
449
|| marginParams .leftMargin != newLeftMargin
491
450
|| marginParams .rightMargin != newRightMargin
492
451
|| marginParams .topMargin != newTopMargin ;
452
+
493
453
if (marginChanged ) {
494
454
marginParams .bottomMargin = newBottomMargin ;
495
455
marginParams .leftMargin = newLeftMargin ;
496
456
marginParams .rightMargin = newRightMargin ;
497
457
marginParams .topMargin = newTopMargin ;
458
+
498
459
view .requestLayout ();
499
460
}
461
+ }
500
462
501
- if (marginChanged || appliedBottomMarginGestureInset != extraBottomMarginGestureInset ) {
502
- if (VERSION .SDK_INT >= VERSION_CODES .Q && shouldUpdateGestureInset ()) {
503
- // Ensure there is only one gesture inset runnable running at a time
504
- view .removeCallbacks (bottomMarginGestureInsetRunnable );
505
- view .post (bottomMarginGestureInsetRunnable );
506
- }
463
+ private int calculateExtraBottomMargin () {
464
+ final boolean respectMandatoryGestureInsets = respectMandatoryGestureInsets ();
465
+
466
+ View anchorView = getAnchorView ();
467
+ if (anchorView != null ) {
468
+ return calculateExtraBottomMarginAnchored (anchorView , respectMandatoryGestureInsets );
469
+ } else {
470
+ return calculateExtraBottomMarginUnanchored (respectMandatoryGestureInsets );
507
471
}
508
472
}
509
473
510
- private boolean shouldUpdateGestureInset () {
511
- return extraBottomMarginGestureInset > 0 && !gestureInsetBottomIgnored && isSwipeDismissable ();
474
+ private boolean respectMandatoryGestureInsets () {
475
+ return VERSION .SDK_INT >= VERSION_CODES .Q
476
+ && extraBottomMarginGestureInset > 0
477
+ && !gestureInsetBottomIgnored
478
+ && isSwipeDismissable ();
512
479
}
513
480
514
481
private boolean isSwipeDismissable () {
@@ -518,6 +485,45 @@ private boolean isSwipeDismissable() {
518
485
instanceof SwipeDismissBehavior ;
519
486
}
520
487
488
+ private int calculateExtraBottomMarginAnchored (
489
+ @ NonNull View anchorView , boolean respectMandatoryGestureInsets ) {
490
+ int [] anchorViewLocation = new int [2 ];
491
+ anchorView .getLocationInWindow (anchorViewLocation );
492
+ int anchorViewAbsoluteYTop = anchorViewLocation [1 ];
493
+
494
+ int [] targetParentLocation = new int [2 ];
495
+ targetParent .getLocationInWindow (targetParentLocation );
496
+ int targetParentAbsoluteYBottom = targetParentLocation [1 ] + targetParent .getHeight ();
497
+
498
+ if (respectMandatoryGestureInsets ) {
499
+ int windowHeight = WindowUtils .getCurrentWindowBounds (context ).height ();
500
+ int maxBottomBarAbsoluteYBottom = Math .min (
501
+ anchorViewAbsoluteYTop ,
502
+ windowHeight - extraBottomMarginGestureInset );
503
+
504
+ return Math .max (targetParentAbsoluteYBottom - maxBottomBarAbsoluteYBottom , 0 );
505
+ } else {
506
+ return targetParentAbsoluteYBottom - anchorViewAbsoluteYTop ;
507
+ }
508
+ }
509
+
510
+ private int calculateExtraBottomMarginUnanchored (boolean respectMandatoryGestureInsets ) {
511
+ if (respectMandatoryGestureInsets ) {
512
+ int [] targetParentLocation = new int [2 ];
513
+ targetParent .getLocationInWindow (targetParentLocation );
514
+ int targetParentAbsoluteYBottom = targetParentLocation [1 ] + targetParent .getHeight ();
515
+
516
+ int windowHeight = WindowUtils .getCurrentWindowBounds (context ).height ();
517
+ int maxBottomBarAbsoluteYBottom = Math .min (
518
+ targetParentAbsoluteYBottom - extraBottomMarginWindowInset ,
519
+ windowHeight - extraBottomMarginGestureInset );
520
+
521
+ return Math .max (targetParentAbsoluteYBottom - maxBottomBarAbsoluteYBottom , 0 );
522
+ } else {
523
+ return extraBottomMarginWindowInset ;
524
+ }
525
+ }
526
+
521
527
@ LayoutRes
522
528
protected int getSnackbarBaseLayoutResId () {
523
529
return hasSnackbarStyleAttr () ? R .layout .mtrl_layout_snackbar : R .layout .design_layout_snackbar ;
@@ -781,7 +787,7 @@ final void showView() {
781
787
}
782
788
783
789
this .view .addToTargetParent (targetParent );
784
- recalculateAndUpdateMargins ();
790
+ updateMargins ();
785
791
786
792
// Set view to INVISIBLE so it doesn't flash on the screen before the inset adjustment is
787
793
// handled and the enter animation is started
@@ -843,12 +849,6 @@ private void showViewImpl() {
843
849
}
844
850
}
845
851
846
- private int getViewAbsoluteBottom () {
847
- int [] absoluteLocation = new int [2 ];
848
- view .getLocationInWindow (absoluteLocation );
849
- return absoluteLocation [1 ] + view .getHeight ();
850
- }
851
-
852
852
private void setUpBehavior (CoordinatorLayout .LayoutParams lp ) {
853
853
// If our LayoutParams are from a CoordinatorLayout, we'll setup our Behavior
854
854
CoordinatorLayout .LayoutParams clp = lp ;
@@ -895,27 +895,6 @@ public void onDragStateChanged(int state) {
895
895
}
896
896
}
897
897
898
- private void recalculateAndUpdateMargins () {
899
- extraBottomMarginAnchorView = calculateBottomMarginForAnchorView ();
900
- updateMargins ();
901
- }
902
-
903
- private int calculateBottomMarginForAnchorView () {
904
- if (getAnchorView () == null ) {
905
- return 0 ;
906
- }
907
-
908
- int [] anchorViewLocation = new int [2 ];
909
- getAnchorView ().getLocationOnScreen (anchorViewLocation );
910
- int anchorViewAbsoluteYTop = anchorViewLocation [1 ];
911
-
912
- int [] targetParentLocation = new int [2 ];
913
- targetParent .getLocationOnScreen (targetParentLocation );
914
- int targetParentAbsoluteYBottom = targetParentLocation [1 ] + targetParent .getHeight ();
915
-
916
- return targetParentAbsoluteYBottom - anchorViewAbsoluteYTop ;
917
- }
918
-
919
898
void animateViewIn () {
920
899
// Post to make sure animation doesn't start until after all inset handling has completed
921
900
view .post (
@@ -1506,7 +1485,7 @@ public void onGlobalLayout() {
1506
1485
|| !transientBottomBar .get ().anchorViewLayoutListenerEnabled ) {
1507
1486
return ;
1508
1487
}
1509
- transientBottomBar .get ().recalculateAndUpdateMargins ();
1488
+ transientBottomBar .get ().updateMargins ();
1510
1489
}
1511
1490
1512
1491
@ Nullable
0 commit comments