diff --git a/docs/components/BottomAppBar.md b/docs/components/BottomAppBar.md index f5ff8ac82f8..ecfba64c238 100644 --- a/docs/components/BottomAppBar.md +++ b/docs/components/BottomAppBar.md @@ -238,6 +238,7 @@ Element | Attribute | Related **Cradle margin** | `app:fabCradleMargin` | `setFabCradleMargin`
`getFabCradleMargin` | `6dp` **Cradle rounded corner radius** | `app:fabCradleRoundedCornerRadius` | `setFabCradleRoundedCornerRadius`
`getFabCradleRoundedCornerRadius` | `4dp` **Cradle vertical offset** | `app:fabCradleVerticalOffset` | `setCradleVerticalOffset`
`getCradleVerticalOffset` | `12dp` +**End margin** | `app:fabAlignmentModeEndMargin` | `setFabAlignmentModeEndMargin`
`getFabAlignmentModeEndMargin` | N/A See the [FAB documentation](https://github.com/material-components/material-components-android/tree/master/docs/components/FloatingActionButton.md) diff --git a/lib/java/com/google/android/material/bottomappbar/BottomAppBar.java b/lib/java/com/google/android/material/bottomappbar/BottomAppBar.java index d30ac4af75a..c8d0e3d3652 100644 --- a/lib/java/com/google/android/material/bottomappbar/BottomAppBar.java +++ b/lib/java/com/google/android/material/bottomappbar/BottomAppBar.java @@ -180,15 +180,21 @@ public class BottomAppBar extends Toolbar implements AttachedBehavior { public @interface MenuAlignmentMode {} @Nullable private Integer navigationIconTint; - private final int fabOffsetEndMode; private final MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable(); @Nullable private Animator modeAnimator; @Nullable private Animator menuAnimator; + @MenuAlignmentMode private int menuAlignmentMode; @FabAlignmentMode private int fabAlignmentMode; @FabAnimationMode private int fabAnimationMode; @FabAnchorMode private int fabAnchorMode; - @MenuAlignmentMode private int menuAlignmentMode; + + /** No end margin for the FAB. */ + private static final int NO_FAB_END_MARGIN = -1; + + private final int fabOffsetEndMode; + @Px private int fabAlignmentModeEndMargin; + private boolean hideOnScroll; private final boolean paddingBottomSystemWindowInsets; private final boolean paddingLeftSystemWindowInsets; @@ -328,6 +334,9 @@ public BottomAppBar(@NonNull Context context, @Nullable AttributeSet attrs, int a.getBoolean(R.styleable.BottomAppBar_paddingLeftSystemWindowInsets, false); paddingRightSystemWindowInsets = a.getBoolean(R.styleable.BottomAppBar_paddingRightSystemWindowInsets, false); + fabAlignmentModeEndMargin = + a.getDimensionPixelOffset( + R.styleable.BottomAppBar_fabAlignmentModeEndMargin, NO_FAB_END_MARGIN); a.recycle(); @@ -600,6 +609,29 @@ public void setCradleVerticalOffset(@Dimension float verticalOffset) { } } + /** + * Returns the {@link FloatingActionButton} end margin pixel offset for the fab if it is set. + * + *

An end margin of -1 indicates that the default margin will be used. + */ + @Px + public int getFabAlignmentModeEndMargin() { + return fabAlignmentModeEndMargin; + } + + /** + * Sets the end margin, in pixels, of the {@link FloatingActionButton}. This will only have an + * effect if the fab alignment mode is {@link #FAB_ALIGNMENT_MODE_END}. + * + *

An offset of -1 will use the default margin. + */ + public void setFabAlignmentModeEndMargin(@Px int margin) { + if (fabAlignmentModeEndMargin != margin) { + fabAlignmentModeEndMargin = margin; + setCutoutStateAndTranslateFab(); + } + } + /** * Returns true if the {@link BottomAppBar} should hide when a {@link * androidx.core.view.NestedScrollingChild} is scrolled. This is handled by {@link @@ -994,8 +1026,17 @@ private float getFabTranslationY() { private float getFabTranslationX(@FabAlignmentMode int fabAlignmentMode) { boolean isRtl = ViewUtils.isLayoutRtl(this); if (fabAlignmentMode == FAB_ALIGNMENT_MODE_END) { + View fab = findDependentView(); int systemEndInset = isRtl ? leftInset : rightInset; - int totalEndInset = fabOffsetEndMode + systemEndInset; + int totalEndInset = systemEndInset; + if (fabAlignmentModeEndMargin != NO_FAB_END_MARGIN && fab != null) { + totalEndInset += fab.getMeasuredWidth() / 2 + fabAlignmentModeEndMargin; + } else { + // If no fab end margin is specified, it follows the previous behaviour of + // translating by fabOffsetEndMode instead of a clear-cut margin. + // This will result in a different padding for different FAB sizes. + totalEndInset += fabOffsetEndMode; + } return (getMeasuredWidth() / 2 - totalEndInset) * (isRtl ? -1 : 1); } else { return 0; diff --git a/lib/java/com/google/android/material/bottomappbar/res-public/values/public.xml b/lib/java/com/google/android/material/bottomappbar/res-public/values/public.xml index daccc88a883..978dd3bb515 100644 --- a/lib/java/com/google/android/material/bottomappbar/res-public/values/public.xml +++ b/lib/java/com/google/android/material/bottomappbar/res-public/values/public.xml @@ -22,6 +22,7 @@ + diff --git a/lib/java/com/google/android/material/bottomappbar/res/values/attrs.xml b/lib/java/com/google/android/material/bottomappbar/res/values/attrs.xml index a1d0eae715f..5a180248ab8 100644 --- a/lib/java/com/google/android/material/bottomappbar/res/values/attrs.xml +++ b/lib/java/com/google/android/material/bottomappbar/res/values/attrs.xml @@ -50,6 +50,8 @@ + +