@@ -300,35 +300,20 @@ public void run() {
300300 }
301301 };
302302
303- @ Nullable private Rect originalMargins ;
304303 private int extraBottomMarginWindowInset ;
305304 private int extraLeftMarginWindowInset ;
306305 private int extraRightMarginWindowInset ;
307306 private int extraBottomMarginGestureInset ;
308307 private int extraBottomMarginAnchorView ;
309308
309+ private boolean pendingShowingView ;
310+
310311 private List <BaseCallback <B >> callbacks ;
311312
312313 private BaseTransientBottomBar .Behavior behavior ;
313314
314315 @ Nullable private final AccessibilityManager accessibilityManager ;
315316
316- /** @hide */
317- // TODO(b/76413401): make package private after the widget migration is finished
318- @ RestrictTo (LIBRARY_GROUP )
319- protected interface OnLayoutChangeListener {
320- void onLayoutChange (View view , int left , int top , int right , int bottom );
321- }
322-
323- /** @hide */
324- // TODO(b/76413401): make package private after the widget migration is finished
325- @ RestrictTo (LIBRARY_GROUP )
326- protected interface OnAttachStateChangeListener {
327- void onViewAttachedToWindow (View v );
328-
329- void onViewDetachedFromWindow (View v );
330- }
331-
332317 /**
333318 * Constructor for the transient bottom bar.
334319 *
@@ -371,24 +356,14 @@ protected BaseTransientBottomBar(
371356 // in the extending Snackbar class. This is to prevent breakage of apps that have custom
372357 // coordinator layout behaviors that depend on that layout.
373358 view = (SnackbarBaseLayout ) inflater .inflate (getSnackbarBaseLayoutResId (), targetParent , false );
359+ view .setBaseTransientBottomBar (this );
374360 if (content instanceof SnackbarContentLayout ) {
375361 ((SnackbarContentLayout ) content )
376362 .updateActionTextColorAlphaIfNeeded (view .getActionTextColorAlpha ());
377363 ((SnackbarContentLayout ) content ).setMaxInlineActionWidth (view .getMaxInlineActionWidth ());
378364 }
379365 view .addView (content );
380366
381- LayoutParams layoutParams = view .getLayoutParams ();
382- if (layoutParams instanceof MarginLayoutParams ) {
383- MarginLayoutParams marginParams = (MarginLayoutParams ) layoutParams ;
384- originalMargins =
385- new Rect (
386- marginParams .leftMargin ,
387- marginParams .topMargin ,
388- marginParams .rightMargin ,
389- marginParams .bottomMargin );
390- }
391-
392367 ViewCompat .setAccessibilityLiveRegion (view , ViewCompat .ACCESSIBILITY_LIVE_REGION_POLITE );
393368 ViewCompat .setImportantForAccessibility (view , ViewCompat .IMPORTANT_FOR_ACCESSIBILITY_YES );
394369
@@ -438,17 +413,23 @@ public boolean performAccessibilityAction(View host, int action, Bundle args) {
438413
439414 private void updateMargins () {
440415 LayoutParams layoutParams = view .getLayoutParams ();
441- if (!(layoutParams instanceof MarginLayoutParams ) || originalMargins == null ) {
416+ if (!(layoutParams instanceof MarginLayoutParams ) || view . originalMargins == null ) {
442417 Log .w (TAG , "Unable to update margins because layout params are not MarginLayoutParams" );
443418 return ;
444419 }
420+ if (view .getParent () == null ) {
421+ // Parent will set layout params to view again. Wait for addView() is done to update layout
422+ // params, in case we save the already updated margins as the original margins.
423+ return ;
424+ }
445425
446426 int extraBottomMargin =
447427 getAnchorView () != null ? extraBottomMarginAnchorView : extraBottomMarginWindowInset ;
448428 MarginLayoutParams marginParams = (MarginLayoutParams ) layoutParams ;
449- marginParams .bottomMargin = originalMargins .bottom + extraBottomMargin ;
450- marginParams .leftMargin = originalMargins .left + extraLeftMarginWindowInset ;
451- marginParams .rightMargin = originalMargins .right + extraRightMarginWindowInset ;
429+ marginParams .bottomMargin = view .originalMargins .bottom + extraBottomMargin ;
430+ marginParams .leftMargin = view .originalMargins .left + extraLeftMarginWindowInset ;
431+ marginParams .rightMargin = view .originalMargins .right + extraRightMarginWindowInset ;
432+ marginParams .topMargin = view .originalMargins .top ;
452433 view .requestLayout ();
453434
454435 if (VERSION .SDK_INT >= VERSION_CODES .Q && shouldUpdateGestureInset ()) {
@@ -724,47 +705,15 @@ protected SwipeDismissBehavior<? extends View> getNewBehavior() {
724705 }
725706
726707 final void showView () {
727- this .view .setOnAttachStateChangeListener (
728- new BaseTransientBottomBar .OnAttachStateChangeListener () {
729- @ Override
730- public void onViewAttachedToWindow (View v ) {
731- if (VERSION .SDK_INT >= VERSION_CODES .Q ) {
732- WindowInsets insets = view .getRootWindowInsets ();
733- if (insets != null ) {
734- extraBottomMarginGestureInset = insets .getMandatorySystemGestureInsets ().bottom ;
735- updateMargins ();
736- }
737- }
738- }
739-
740- @ Override
741- public void onViewDetachedFromWindow (View v ) {
742- if (isShownOrQueued ()) {
743- // If we haven't already been dismissed then this event is coming from a
744- // non-user initiated action. Hence we need to make sure that we callback
745- // and keep our state up to date. We need to post the call since
746- // removeView() will call through to onDetachedFromWindow and thus overflow.
747- handler .post (
748- new Runnable () {
749- @ Override
750- public void run () {
751- onViewHidden (BaseCallback .DISMISS_EVENT_MANUAL );
752- }
753- });
754- }
755- }
756- });
757-
758708 if (this .view .getParent () == null ) {
759709 ViewGroup .LayoutParams lp = this .view .getLayoutParams ();
760710
761711 if (lp instanceof CoordinatorLayout .LayoutParams ) {
762712 setUpBehavior ((CoordinatorLayout .LayoutParams ) lp );
763713 }
764714
765- recalculateAndUpdateMargins ();
766-
767715 targetParent .addView (this .view );
716+ recalculateAndUpdateMargins ();
768717
769718 // Set view to INVISIBLE so it doesn't flash on the screen before the inset adjustment is
770719 // handled and the enter animation is started
@@ -776,15 +725,41 @@ public void run() {
776725 return ;
777726 }
778727
779- // Otherwise, add one of our layout change listeners and show it in when laid out
780- this .view .setOnLayoutChangeListener (
781- new OnLayoutChangeListener () {
782- @ Override
783- public void onLayoutChange (View view , int left , int top , int right , int bottom ) {
784- BaseTransientBottomBar .this .view .setOnLayoutChangeListener (null );
785- BaseTransientBottomBar .this .showViewImpl ();
786- }
787- });
728+ // Otherwise, show it in when laid out
729+ pendingShowingView = true ;
730+ }
731+
732+ void onAttachedToWindow () {
733+ if (VERSION .SDK_INT >= VERSION_CODES .Q ) {
734+ WindowInsets insets = view .getRootWindowInsets ();
735+ if (insets != null ) {
736+ extraBottomMarginGestureInset = insets .getMandatorySystemGestureInsets ().bottom ;
737+ updateMargins ();
738+ }
739+ }
740+ }
741+
742+ void onDetachedFromWindow () {
743+ if (isShownOrQueued ()) {
744+ // If we haven't already been dismissed then this event is coming from a
745+ // non-user initiated action. Hence we need to make sure that we callback
746+ // and keep our state up to date. We need to post the call since
747+ // removeView() will call through to onDetachedFromWindow and thus overflow.
748+ handler .post (
749+ new Runnable () {
750+ @ Override
751+ public void run () {
752+ onViewHidden (BaseCallback .DISMISS_EVENT_MANUAL );
753+ }
754+ });
755+ }
756+ }
757+
758+ void onLayoutChange () {
759+ if (pendingShowingView ) {
760+ BaseTransientBottomBar .this .showViewImpl ();
761+ pendingShowingView = false ;
762+ }
788763 }
789764
790765 private void showViewImpl () {
@@ -1116,7 +1091,6 @@ boolean shouldAnimate() {
11161091 /** @hide */
11171092 @ RestrictTo (LIBRARY_GROUP )
11181093 protected static class SnackbarBaseLayout extends FrameLayout {
1119-
11201094 private static final OnTouchListener consumeAllTouchListener =
11211095 new OnTouchListener () {
11221096 @ SuppressLint ("ClickableViewAccessibility" )
@@ -1127,8 +1101,7 @@ public boolean onTouch(View v, MotionEvent event) {
11271101 }
11281102 };
11291103
1130- private BaseTransientBottomBar .OnLayoutChangeListener onLayoutChangeListener ;
1131- private BaseTransientBottomBar .OnAttachStateChangeListener onAttachStateChangeListener ;
1104+ @ Nullable private BaseTransientBottomBar <?> baseTransientBottomBar ;
11321105 @ AnimationMode private int animationMode ;
11331106 private final float backgroundOverlayColorAlpha ;
11341107 private final float actionTextColorAlpha ;
@@ -1137,6 +1110,8 @@ public boolean onTouch(View v, MotionEvent event) {
11371110 private ColorStateList backgroundTint ;
11381111 private PorterDuff .Mode backgroundTintMode ;
11391112
1113+ @ Nullable private Rect originalMargins ;
1114+
11401115 protected SnackbarBaseLayout (@ NonNull Context context ) {
11411116 this (context , null );
11421117 }
@@ -1233,37 +1208,37 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
12331208 @ Override
12341209 protected void onLayout (boolean changed , int l , int t , int r , int b ) {
12351210 super .onLayout (changed , l , t , r , b );
1236- if (onLayoutChangeListener != null ) {
1237- onLayoutChangeListener .onLayoutChange (this , l , t , r , b );
1211+ if (baseTransientBottomBar != null ) {
1212+ baseTransientBottomBar .onLayoutChange ();
12381213 }
12391214 }
12401215
12411216 @ Override
12421217 protected void onAttachedToWindow () {
12431218 super .onAttachedToWindow ();
1244- if (onAttachStateChangeListener != null ) {
1245- onAttachStateChangeListener . onViewAttachedToWindow ( this );
1219+ if (baseTransientBottomBar != null ) {
1220+ baseTransientBottomBar . onAttachedToWindow ( );
12461221 }
1247-
12481222 ViewCompat .requestApplyInsets (this );
12491223 }
12501224
12511225 @ Override
12521226 protected void onDetachedFromWindow () {
12531227 super .onDetachedFromWindow ();
1254- if (onAttachStateChangeListener != null ) {
1255- onAttachStateChangeListener . onViewDetachedFromWindow ( this );
1228+ if (baseTransientBottomBar != null ) {
1229+ baseTransientBottomBar . onDetachedFromWindow ( );
12561230 }
12571231 }
12581232
1259- void setOnLayoutChangeListener (
1260- BaseTransientBottomBar .OnLayoutChangeListener onLayoutChangeListener ) {
1261- this .onLayoutChangeListener = onLayoutChangeListener ;
1262- }
1263-
1264- void setOnAttachStateChangeListener (
1265- BaseTransientBottomBar .OnAttachStateChangeListener listener ) {
1266- onAttachStateChangeListener = listener ;
1233+ @ Override
1234+ public void setLayoutParams (ViewGroup .LayoutParams params ) {
1235+ super .setLayoutParams (params );
1236+ if (params instanceof MarginLayoutParams ) {
1237+ updateOriginalMargins ((MarginLayoutParams ) params );
1238+ if (baseTransientBottomBar != null ) {
1239+ baseTransientBottomBar .updateMargins ();
1240+ }
1241+ }
12671242 }
12681243
12691244 @ AnimationMode
@@ -1291,6 +1266,15 @@ int getMaxInlineActionWidth() {
12911266 return maxInlineActionWidth ;
12921267 }
12931268
1269+ private void setBaseTransientBottomBar (BaseTransientBottomBar <?> baseTransientBottomBar ) {
1270+ this .baseTransientBottomBar = baseTransientBottomBar ;
1271+ }
1272+
1273+ private void updateOriginalMargins (MarginLayoutParams params ) {
1274+ originalMargins =
1275+ new Rect (params .leftMargin , params .topMargin , params .rightMargin , params .bottomMargin );
1276+ }
1277+
12941278 @ NonNull
12951279 private Drawable createThemedBackground () {
12961280 float cornerRadius =
0 commit comments