Skip to content

Commit 11854e6

Browse files
committed
[Snackbar] Refactor mandatory system gesture insets handling
1 parent cfef899 commit 11854e6

File tree

1 file changed

+63
-84
lines changed

1 file changed

+63
-84
lines changed

lib/java/com/google/android/material/snackbar/BaseTransientBottomBar.java

Lines changed: 63 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
import androidx.annotation.LayoutRes;
6969
import androidx.annotation.NonNull;
7070
import androidx.annotation.Nullable;
71-
import androidx.annotation.RequiresApi;
7271
import androidx.annotation.RestrictTo;
7372
import androidx.coordinatorlayout.widget.CoordinatorLayout;
7473
import androidx.core.graphics.drawable.DrawableCompat;
@@ -284,49 +283,11 @@ public boolean handleMessage(@NonNull Message message) {
284283

285284
private boolean anchorViewLayoutListenerEnabled = false;
286285

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-
323286
private int extraBottomMarginWindowInset;
324287
private int extraLeftMarginWindowInset;
325288
private int extraRightMarginWindowInset;
326-
private int extraBottomMarginAnchorView;
327289

328290
private int extraBottomMarginGestureInset;
329-
private int appliedBottomMarginGestureInset;
330291

331292
private boolean pendingShowingView;
332293

@@ -476,39 +437,45 @@ private void updateMargins() {
476437
return;
477438
}
478439

479-
int extraBottomMargin =
480-
getAnchorView() != null ? extraBottomMarginAnchorView : extraBottomMarginWindowInset;
481-
482440
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;
487441

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 =
489448
marginParams.bottomMargin != newBottomMargin
490449
|| marginParams.leftMargin != newLeftMargin
491450
|| marginParams.rightMargin != newRightMargin
492451
|| marginParams.topMargin != newTopMargin;
452+
493453
if (marginChanged) {
494454
marginParams.bottomMargin = newBottomMargin;
495455
marginParams.leftMargin = newLeftMargin;
496456
marginParams.rightMargin = newRightMargin;
497457
marginParams.topMargin = newTopMargin;
458+
498459
view.requestLayout();
499460
}
461+
}
500462

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);
507471
}
508472
}
509473

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();
512479
}
513480

514481
private boolean isSwipeDismissable() {
@@ -518,6 +485,45 @@ private boolean isSwipeDismissable() {
518485
instanceof SwipeDismissBehavior;
519486
}
520487

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+
521527
@LayoutRes
522528
protected int getSnackbarBaseLayoutResId() {
523529
return hasSnackbarStyleAttr() ? R.layout.mtrl_layout_snackbar : R.layout.design_layout_snackbar;
@@ -781,7 +787,7 @@ final void showView() {
781787
}
782788

783789
this.view.addToTargetParent(targetParent);
784-
recalculateAndUpdateMargins();
790+
updateMargins();
785791

786792
// Set view to INVISIBLE so it doesn't flash on the screen before the inset adjustment is
787793
// handled and the enter animation is started
@@ -843,12 +849,6 @@ private void showViewImpl() {
843849
}
844850
}
845851

846-
private int getViewAbsoluteBottom() {
847-
int[] absoluteLocation = new int[2];
848-
view.getLocationInWindow(absoluteLocation);
849-
return absoluteLocation[1] + view.getHeight();
850-
}
851-
852852
private void setUpBehavior(CoordinatorLayout.LayoutParams lp) {
853853
// If our LayoutParams are from a CoordinatorLayout, we'll setup our Behavior
854854
CoordinatorLayout.LayoutParams clp = lp;
@@ -895,27 +895,6 @@ public void onDragStateChanged(int state) {
895895
}
896896
}
897897

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-
919898
void animateViewIn() {
920899
// Post to make sure animation doesn't start until after all inset handling has completed
921900
view.post(
@@ -1506,7 +1485,7 @@ public void onGlobalLayout() {
15061485
|| !transientBottomBar.get().anchorViewLayoutListenerEnabled) {
15071486
return;
15081487
}
1509-
transientBottomBar.get().recalculateAndUpdateMargins();
1488+
transientBottomBar.get().updateMargins();
15101489
}
15111490

15121491
@Nullable

0 commit comments

Comments
 (0)