Skip to content

Commit

Permalink
[Snackbar] Fix the issue that setting margins programmatically does n…
Browse files Browse the repository at this point in the history
…ot work

We always use the original margins saved when the snackbar is created to update snackbar's actual margins. Therefore the newly set margins will always be overridden. Fixes this by updating original margins when layout params are set.

Resolves #1076

PiperOrigin-RevId: 427795853
  • Loading branch information
drchen authored and raajkumars committed Feb 11, 2022
1 parent 6c1bdd7 commit d5856fd
Showing 1 changed file with 76 additions and 92 deletions.
Expand Up @@ -300,35 +300,20 @@ public void run() {
}
};

@Nullable private Rect originalMargins;
private int extraBottomMarginWindowInset;
private int extraLeftMarginWindowInset;
private int extraRightMarginWindowInset;
private int extraBottomMarginGestureInset;
private int extraBottomMarginAnchorView;

private boolean pendingShowingView;

private List<BaseCallback<B>> callbacks;

private BaseTransientBottomBar.Behavior behavior;

@Nullable private final AccessibilityManager accessibilityManager;

/** @hide */
// TODO(b/76413401): make package private after the widget migration is finished
@RestrictTo(LIBRARY_GROUP)
protected interface OnLayoutChangeListener {
void onLayoutChange(View view, int left, int top, int right, int bottom);
}

/** @hide */
// TODO(b/76413401): make package private after the widget migration is finished
@RestrictTo(LIBRARY_GROUP)
protected interface OnAttachStateChangeListener {
void onViewAttachedToWindow(View v);

void onViewDetachedFromWindow(View v);
}

/**
* Constructor for the transient bottom bar.
*
Expand Down Expand Up @@ -371,24 +356,14 @@ protected BaseTransientBottomBar(
// in the extending Snackbar class. This is to prevent breakage of apps that have custom
// coordinator layout behaviors that depend on that layout.
view = (SnackbarBaseLayout) inflater.inflate(getSnackbarBaseLayoutResId(), targetParent, false);
view.setBaseTransientBottomBar(this);
if (content instanceof SnackbarContentLayout) {
((SnackbarContentLayout) content)
.updateActionTextColorAlphaIfNeeded(view.getActionTextColorAlpha());
((SnackbarContentLayout) content).setMaxInlineActionWidth(view.getMaxInlineActionWidth());
}
view.addView(content);

LayoutParams layoutParams = view.getLayoutParams();
if (layoutParams instanceof MarginLayoutParams) {
MarginLayoutParams marginParams = (MarginLayoutParams) layoutParams;
originalMargins =
new Rect(
marginParams.leftMargin,
marginParams.topMargin,
marginParams.rightMargin,
marginParams.bottomMargin);
}

ViewCompat.setAccessibilityLiveRegion(view, ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE);
ViewCompat.setImportantForAccessibility(view, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);

Expand Down Expand Up @@ -438,17 +413,23 @@ public boolean performAccessibilityAction(View host, int action, Bundle args) {

private void updateMargins() {
LayoutParams layoutParams = view.getLayoutParams();
if (!(layoutParams instanceof MarginLayoutParams) || originalMargins == null) {
if (!(layoutParams instanceof MarginLayoutParams) || view.originalMargins == null) {
Log.w(TAG, "Unable to update margins because layout params are not MarginLayoutParams");
return;
}
if (view.getParent() == null) {
// Parent will set layout params to view again. Wait for addView() is done to update layout
// params, in case we save the already updated margins as the original margins.
return;
}

int extraBottomMargin =
getAnchorView() != null ? extraBottomMarginAnchorView : extraBottomMarginWindowInset;
MarginLayoutParams marginParams = (MarginLayoutParams) layoutParams;
marginParams.bottomMargin = originalMargins.bottom + extraBottomMargin;
marginParams.leftMargin = originalMargins.left + extraLeftMarginWindowInset;
marginParams.rightMargin = originalMargins.right + extraRightMarginWindowInset;
marginParams.bottomMargin = view.originalMargins.bottom + extraBottomMargin;
marginParams.leftMargin = view.originalMargins.left + extraLeftMarginWindowInset;
marginParams.rightMargin = view.originalMargins.right + extraRightMarginWindowInset;
marginParams.topMargin = view.originalMargins.top;
view.requestLayout();

if (VERSION.SDK_INT >= VERSION_CODES.Q && shouldUpdateGestureInset()) {
Expand Down Expand Up @@ -724,47 +705,15 @@ protected SwipeDismissBehavior<? extends View> getNewBehavior() {
}

final void showView() {
this.view.setOnAttachStateChangeListener(
new BaseTransientBottomBar.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
if (VERSION.SDK_INT >= VERSION_CODES.Q) {
WindowInsets insets = view.getRootWindowInsets();
if (insets != null) {
extraBottomMarginGestureInset = insets.getMandatorySystemGestureInsets().bottom;
updateMargins();
}
}
}

@Override
public void onViewDetachedFromWindow(View v) {
if (isShownOrQueued()) {
// If we haven't already been dismissed then this event is coming from a
// non-user initiated action. Hence we need to make sure that we callback
// and keep our state up to date. We need to post the call since
// removeView() will call through to onDetachedFromWindow and thus overflow.
handler.post(
new Runnable() {
@Override
public void run() {
onViewHidden(BaseCallback.DISMISS_EVENT_MANUAL);
}
});
}
}
});

if (this.view.getParent() == null) {
ViewGroup.LayoutParams lp = this.view.getLayoutParams();

if (lp instanceof CoordinatorLayout.LayoutParams) {
setUpBehavior((CoordinatorLayout.LayoutParams) lp);
}

recalculateAndUpdateMargins();

targetParent.addView(this.view);
recalculateAndUpdateMargins();

// Set view to INVISIBLE so it doesn't flash on the screen before the inset adjustment is
// handled and the enter animation is started
Expand All @@ -776,15 +725,41 @@ public void run() {
return;
}

// Otherwise, add one of our layout change listeners and show it in when laid out
this.view.setOnLayoutChangeListener(
new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View view, int left, int top, int right, int bottom) {
BaseTransientBottomBar.this.view.setOnLayoutChangeListener(null);
BaseTransientBottomBar.this.showViewImpl();
}
});
// Otherwise, show it in when laid out
pendingShowingView = true;
}

void onAttachedToWindow() {
if (VERSION.SDK_INT >= VERSION_CODES.Q) {
WindowInsets insets = view.getRootWindowInsets();
if (insets != null) {
extraBottomMarginGestureInset = insets.getMandatorySystemGestureInsets().bottom;
updateMargins();
}
}
}

void onDetachedFromWindow() {
if (isShownOrQueued()) {
// If we haven't already been dismissed then this event is coming from a
// non-user initiated action. Hence we need to make sure that we callback
// and keep our state up to date. We need to post the call since
// removeView() will call through to onDetachedFromWindow and thus overflow.
handler.post(
new Runnable() {
@Override
public void run() {
onViewHidden(BaseCallback.DISMISS_EVENT_MANUAL);
}
});
}
}

void onLayoutChange() {
if (pendingShowingView) {
BaseTransientBottomBar.this.showViewImpl();
pendingShowingView = false;
}
}

private void showViewImpl() {
Expand Down Expand Up @@ -1116,7 +1091,6 @@ boolean shouldAnimate() {
/** @hide */
@RestrictTo(LIBRARY_GROUP)
protected static class SnackbarBaseLayout extends FrameLayout {

private static final OnTouchListener consumeAllTouchListener =
new OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
Expand All @@ -1127,8 +1101,7 @@ public boolean onTouch(View v, MotionEvent event) {
}
};

private BaseTransientBottomBar.OnLayoutChangeListener onLayoutChangeListener;
private BaseTransientBottomBar.OnAttachStateChangeListener onAttachStateChangeListener;
@Nullable private BaseTransientBottomBar<?> baseTransientBottomBar;
@AnimationMode private int animationMode;
private final float backgroundOverlayColorAlpha;
private final float actionTextColorAlpha;
Expand All @@ -1137,6 +1110,8 @@ public boolean onTouch(View v, MotionEvent event) {
private ColorStateList backgroundTint;
private PorterDuff.Mode backgroundTintMode;

@Nullable private Rect originalMargins;

protected SnackbarBaseLayout(@NonNull Context context) {
this(context, null);
}
Expand Down Expand Up @@ -1233,37 +1208,37 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (onLayoutChangeListener != null) {
onLayoutChangeListener.onLayoutChange(this, l, t, r, b);
if (baseTransientBottomBar != null) {
baseTransientBottomBar.onLayoutChange();
}
}

@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (onAttachStateChangeListener != null) {
onAttachStateChangeListener.onViewAttachedToWindow(this);
if (baseTransientBottomBar != null) {
baseTransientBottomBar.onAttachedToWindow();
}

ViewCompat.requestApplyInsets(this);
}

@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (onAttachStateChangeListener != null) {
onAttachStateChangeListener.onViewDetachedFromWindow(this);
if (baseTransientBottomBar != null) {
baseTransientBottomBar.onDetachedFromWindow();
}
}

void setOnLayoutChangeListener(
BaseTransientBottomBar.OnLayoutChangeListener onLayoutChangeListener) {
this.onLayoutChangeListener = onLayoutChangeListener;
}

void setOnAttachStateChangeListener(
BaseTransientBottomBar.OnAttachStateChangeListener listener) {
onAttachStateChangeListener = listener;
@Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
super.setLayoutParams(params);
if (params instanceof MarginLayoutParams) {
updateOriginalMargins((MarginLayoutParams) params);
if (baseTransientBottomBar != null) {
baseTransientBottomBar.updateMargins();
}
}
}

@AnimationMode
Expand Down Expand Up @@ -1291,6 +1266,15 @@ int getMaxInlineActionWidth() {
return maxInlineActionWidth;
}

private void setBaseTransientBottomBar(BaseTransientBottomBar<?> baseTransientBottomBar) {
this.baseTransientBottomBar = baseTransientBottomBar;
}

private void updateOriginalMargins(MarginLayoutParams params) {
originalMargins =
new Rect(params.leftMargin, params.topMargin, params.rightMargin, params.bottomMargin);
}

@NonNull
private Drawable createThemedBackground() {
float cornerRadius =
Expand Down

0 comments on commit d5856fd

Please sign in to comment.