Skip to content

Commit a9f95ec

Browse files
cketchamdsn5ft
authored andcommitted
Update BottomAppBar to react to layout changes in FAB
PiperOrigin-RevId: 250527847
1 parent daa3a04 commit a9f95ec

File tree

1 file changed

+52
-18
lines changed

1 file changed

+52
-18
lines changed

lib/java/com/google/android/material/bottomappbar/BottomAppBar.java

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import androidx.coordinatorlayout.widget.CoordinatorLayout.AttachedBehavior;
6464
import java.lang.annotation.Retention;
6565
import java.lang.annotation.RetentionPolicy;
66+
import java.lang.ref.WeakReference;
6667
import java.util.ArrayList;
6768
import java.util.List;
6869

@@ -420,11 +421,14 @@ private void dispatchAnimationEnd() {
420421
* Sets the fab diameter. This will be called automatically by the {@link BottomAppBar.Behavior}
421422
* if the fab is anchored to this {@link BottomAppBar}.
422423
*/
423-
void setFabDiameter(@Px int diameter) {
424+
boolean setFabDiameter(@Px int diameter) {
424425
if (diameter != getTopEdgeTreatment().getFabDiameter()) {
425426
getTopEdgeTreatment().setFabDiameter(diameter);
426427
materialShapeDrawable.invalidateSelf();
428+
return true;
427429
}
430+
431+
return false;
428432
}
429433

430434
private void maybeAnimateModeChange(@FabAlignmentMode int targetMode) {
@@ -810,6 +814,47 @@ public static class Behavior extends HideBottomViewOnScrollBehavior<BottomAppBar
810814

811815
private final Rect fabContentRect;
812816

817+
private WeakReference<BottomAppBar> viewRef;
818+
819+
private final OnLayoutChangeListener fabLayoutListener = new OnLayoutChangeListener() {
820+
@Override
821+
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
822+
int oldTop, int oldRight, int oldBottom) {
823+
BottomAppBar child = viewRef.get();
824+
825+
// If the child BAB no longer exists, remove the listener.
826+
if (child == null || !(v instanceof FloatingActionButton)) {
827+
v.removeOnLayoutChangeListener(this);
828+
return;
829+
}
830+
831+
FloatingActionButton fab = ((FloatingActionButton) v);
832+
833+
fab.getMeasuredContentRect(fabContentRect);
834+
int height = fabContentRect.height();
835+
836+
// Set the cutout diameter based on the height of the fab.
837+
if (!child.setFabDiameter(height)) {
838+
// The size of the fab didn't change so return early.
839+
return;
840+
}
841+
842+
CoordinatorLayout.LayoutParams fabLayoutParams = (CoordinatorLayout.LayoutParams) v
843+
.getLayoutParams();
844+
845+
// Set the bottomMargin of the fab if it is 0dp. This adds space below the fab if the
846+
// BottomAppBar is hidden.
847+
if (fabLayoutParams.bottomMargin == 0) {
848+
// Extra padding is added for the fake shadow on API < 21. Ensure we don't add too much
849+
// space by removing that extra padding.
850+
int bottomShadowPadding = (fab.getMeasuredHeight() - fabContentRect.height()) / 2;
851+
int bottomMargin = child.getResources()
852+
.getDimensionPixelOffset(R.dimen.mtrl_bottomappbar_fab_bottom_margin);
853+
fabLayoutParams.bottomMargin = Math.max(0, bottomMargin - bottomShadowPadding);
854+
}
855+
}
856+
};
857+
813858
public Behavior() {
814859
fabContentRect = new Rect();
815860
}
@@ -822,6 +867,8 @@ public Behavior(Context context, AttributeSet attrs) {
822867
@Override
823868
public boolean onLayoutChild(
824869
CoordinatorLayout parent, BottomAppBar child, int layoutDirection) {
870+
viewRef = new WeakReference<>(child);
871+
825872
View dependentView = child.findDependentView();
826873
if (dependentView != null && !ViewCompat.isLaidOut(dependentView)) {
827874
// Set the initial position of the FloatingActionButton with the BottomAppBar vertical
@@ -832,25 +879,12 @@ public boolean onLayoutChild(
832879

833880
if (dependentView instanceof FloatingActionButton) {
834881
FloatingActionButton fab = ((FloatingActionButton) dependentView);
882+
883+
// Always update the BAB if the fab is laid out.
884+
fab.addOnLayoutChangeListener(fabLayoutListener);
885+
835886
// Ensure the FAB is correctly linked to this BAB so the animations can run correctly
836887
child.addFabAnimationListeners(fab);
837-
838-
// Set the correct cutout diameter
839-
fab.getMeasuredContentRect(fabContentRect);
840-
child.setFabDiameter(fabContentRect.height());
841-
842-
// Set the bottomMargin of the fab if it is 0dp. This adds space below the fab if the
843-
// BottomAppBar is hidden.
844-
if (fabLayoutParams.bottomMargin == 0) {
845-
// Extra padding is added for the fake shadow on API < 21. Ensure we don't add too much
846-
// space by removing that extra padding.
847-
int bottomShadowPadding = (fab.getMeasuredHeight() - fabContentRect.height()) / 2;
848-
int bottomMargin =
849-
child
850-
.getResources()
851-
.getDimensionPixelOffset(R.dimen.mtrl_bottomappbar_fab_bottom_margin);
852-
fabLayoutParams.bottomMargin = Math.max(0, bottomMargin - bottomShadowPadding);
853-
}
854888
}
855889

856890
// Move the fab to the correct position

0 commit comments

Comments
 (0)