1919import com .google .android .material .R ;
2020
2121import static androidx .annotation .RestrictTo .Scope .LIBRARY_GROUP ;
22+ import static com .google .android .material .navigation .NavigationBarView .ACTIVE_INDICATOR_WIDTH_MATCH_PARENT ;
23+ import static com .google .android .material .navigation .NavigationBarView .ACTIVE_INDICATOR_WIDTH_WRAP_CONTENT ;
2224import static com .google .android .material .navigation .NavigationBarView .ITEM_ICON_GRAVITY_START ;
2325import static com .google .android .material .navigation .NavigationBarView .ITEM_ICON_GRAVITY_TOP ;
2426import static java .lang .Math .max ;
@@ -132,11 +134,14 @@ public abstract class NavigationBarItemView extends FrameLayout implements MenuV
132134 // desired width.
133135 private int activeIndicatorDesiredWidth = 0 ;
134136 private int activeIndicatorDesiredHeight = 0 ;
137+ private int activeIndicatorExpandedDesiredWidth = ACTIVE_INDICATOR_WIDTH_WRAP_CONTENT ;
138+ private int activeIndicatorExpandedDesiredHeight = 0 ;
135139 private boolean activeIndicatorResizeable = false ;
136140 // The margin from the start and end of this view which the active indicator should respect. If
137141 // the indicator width is greater than the total width minus the horizontal margins, the active
138142 // indicator will assume the max width of the view's total width minus horizontal margins.
139143 private int activeIndicatorMarginHorizontal = 0 ;
144+ private int activeIndicatorExpandedMarginHorizontal = 0 ;
140145
141146 @ Nullable private BadgeDrawable badgeDrawable ;
142147
@@ -169,6 +174,8 @@ public NavigationBarItemView(@NonNull Context context) {
169174 largeLabel .setImportantForAccessibility (View .IMPORTANT_FOR_ACCESSIBILITY_NO );
170175 setFocusable (true );
171176 calculateTextScaleFactors (smallLabel .getTextSize (), largeLabel .getTextSize ());
177+ activeIndicatorExpandedDesiredHeight = getResources ().getDimensionPixelSize (
178+ R .dimen .m3_expressive_item_expanded_active_indicator_height_default );
172179
173180 // TODO(b/138148581): Support displaying a badge on label-only bottom navigation views.
174181 innerContentContainer .addOnLayoutChangeListener (
@@ -178,7 +185,8 @@ public NavigationBarItemView(@NonNull Context context) {
178185 }
179186 // If item icon gravity is start, we want to update the active indicator width in a layout
180187 // change listener to keep the active indicator size up to date with the content width.
181- if (itemIconGravity == ITEM_ICON_GRAVITY_START ) {
188+ if (itemIconGravity == ITEM_ICON_GRAVITY_START
189+ && activeIndicatorExpandedDesiredWidth == ACTIVE_INDICATOR_WIDTH_WRAP_CONTENT ) {
182190 LayoutParams lp = (LayoutParams ) innerContentContainer .getLayoutParams ();
183191 int newWidth = right - left + lp .rightMargin + lp .leftMargin ;
184192 LayoutParams indicatorParams = (LayoutParams ) activeIndicatorView .getLayoutParams ();
@@ -289,16 +297,18 @@ private void updateItemIconGravity() {
289297 int labelGroupTopMargin = activeIndicatorLabelPadding ;
290298 int labelGroupSideMargin = 0 ;
291299 int sidePadding = 0 ;
300+ int contentGravity = Gravity .CENTER ;
292301 badgeFixedEdge = BadgeDrawable .BADGE_FIXED_EDGE_START ;
293302 if (itemIconGravity == ITEM_ICON_GRAVITY_START ) {
294303 gravity = Gravity .CENTER ;
304+ contentGravity = Gravity .START | Gravity .CENTER_VERTICAL ;
295305 sideMargin =
296306 getResources ()
297307 .getDimensionPixelSize (R .dimen .m3_expressive_navigation_item_leading_trailing_space );
298308 labelGroupTopMargin = 0 ;
299309 labelGroupSideMargin = activeIndicatorLabelPadding ;
300310 badgeFixedEdge = BadgeDrawable .BADGE_FIXED_EDGE_END ;
301- sidePadding = activeIndicatorMarginHorizontal ;
311+ sidePadding = activeIndicatorExpandedMarginHorizontal ;
302312 if (labelGroup .getParent () != innerContentContainer ) {
303313 contentContainer .removeView (labelGroup );
304314 innerContentContainer .addView (labelGroup );
@@ -313,6 +323,7 @@ private void updateItemIconGravity() {
313323 (LayoutParams ) innerContentContainer .getLayoutParams ();
314324 innerContentLp .leftMargin = sideMargin ;
315325 innerContentLp .rightMargin = sideMargin ;
326+ innerContentLp .gravity = contentGravity ;
316327 LinearLayout .LayoutParams labelGroupLp =
317328 (LinearLayout .LayoutParams ) labelGroup .getLayoutParams ();
318329 labelGroupLp .rightMargin =
@@ -458,6 +469,13 @@ private void setLayoutConfigurationIconAndLabel(
458469 itemIconGravity == ITEM_ICON_GRAVITY_TOP
459470 ? Gravity .CENTER_HORIZONTAL | Gravity .TOP
460471 : Gravity .CENTER );
472+ setViewMarginAndGravity (
473+ innerContentContainer ,
474+ 0 ,
475+ 0 ,
476+ itemIconGravity == ITEM_ICON_GRAVITY_TOP
477+ ? Gravity .CENTER
478+ : Gravity .START | Gravity .CENTER_VERTICAL );
461479 updateViewPaddingBottom (
462480 labelGroup , itemIconGravity == ITEM_ICON_GRAVITY_TOP ? itemPaddingBottom : 0 );
463481 labelGroup .setVisibility (VISIBLE );
@@ -467,6 +485,7 @@ private void setLayoutConfigurationIconAndLabel(
467485
468486 private void setLayoutConfigurationIconOnly () {
469487 setViewMarginAndGravity (contentContainer , itemPaddingTop , itemPaddingTop , Gravity .CENTER );
488+ setViewMarginAndGravity (innerContentContainer , 0 , 0 , Gravity .CENTER );
470489 updateViewPaddingBottom (labelGroup , 0 );
471490 labelGroup .setVisibility (GONE );
472491 }
@@ -865,6 +884,28 @@ public void setActiveIndicatorWidth(int width) {
865884 updateActiveIndicatorLayoutParams (getWidth ());
866885 }
867886
887+ /**
888+ * Set the height of the active indicator when it is expanded, ie. the item icon width is set to
889+ * {@link ItemIconGravity#ITEM_ICON_GRAVITY_START}.
890+ *
891+ * @param width The width of the active indicator.
892+ */
893+ public void setActiveIndicatorExpandedWidth (int width ) {
894+ this .activeIndicatorExpandedDesiredWidth = width ;
895+ updateActiveIndicatorLayoutParams (getWidth ());
896+ }
897+
898+ /**
899+ * Set the height of the active indicator when it is expanded, ie. the item icon width is set to *
900+ * {@link ItemIconGravity#ITEM_ICON_GRAVITY_START}.
901+ *
902+ * @param height The height of the active indicator.
903+ */
904+ public void setActiveIndicatorExpandedHeight (int height ) {
905+ this .activeIndicatorExpandedDesiredHeight = height ;
906+ updateActiveIndicatorLayoutParams (getWidth ());
907+ }
908+
868909 /**
869910 * Update the active indicators width and height for the available width and label visibility
870911 * mode.
@@ -882,10 +923,15 @@ private void updateActiveIndicatorLayoutParams(int availableWidth) {
882923 min (activeIndicatorDesiredWidth , availableWidth - (activeIndicatorMarginHorizontal * 2 ));
883924 int newHeight = activeIndicatorDesiredHeight ;
884925 if (itemIconGravity == ITEM_ICON_GRAVITY_START ) {
885- newWidth = max (contentContainer .getMeasuredWidth (), newWidth );
886- newHeight =
887- getResources ()
888- .getDimensionPixelSize (R .dimen .m3_expressive_horizontal_item_active_indicator_height );
926+ int adjustedAvailableWidth = availableWidth - (activeIndicatorExpandedMarginHorizontal * 2 );
927+ if (activeIndicatorExpandedDesiredWidth == ACTIVE_INDICATOR_WIDTH_MATCH_PARENT ) {
928+ newWidth = adjustedAvailableWidth ;
929+ } else if (activeIndicatorExpandedDesiredWidth == ACTIVE_INDICATOR_WIDTH_WRAP_CONTENT ) {
930+ newWidth = contentContainer .getMeasuredWidth ();
931+ } else {
932+ newWidth = min (activeIndicatorExpandedDesiredWidth , adjustedAvailableWidth );
933+ }
934+ newHeight = activeIndicatorExpandedDesiredHeight ;
889935 }
890936 LayoutParams indicatorParams = (LayoutParams ) activeIndicatorView .getLayoutParams ();
891937 // If the label visibility is unlabeled, make the active indicator's height equal to its
@@ -921,6 +967,19 @@ public void setActiveIndicatorHeight(int height) {
921967 */
922968 public void setActiveIndicatorMarginHorizontal (@ Px int marginHorizontal ) {
923969 this .activeIndicatorMarginHorizontal = marginHorizontal ;
970+ updateActiveIndicatorLayoutParams (getWidth ());
971+ }
972+
973+ /**
974+ * Set the horizontal margin that will be maintained at the start and end of the expanded active
975+ * indicator, making sure the indicator remains the given distance from the edge of this item
976+ * view.
977+ *
978+ * @see #updateActiveIndicatorLayoutParams(int)
979+ * @param marginHorizontal The horizontal margin, in pixels.
980+ */
981+ public void setActiveIndicatorExpandedMarginHorizontal (@ Px int marginHorizontal ) {
982+ this .activeIndicatorExpandedMarginHorizontal = marginHorizontal ;
924983 if (itemIconGravity == ITEM_ICON_GRAVITY_START ) {
925984 setPadding (marginHorizontal , 0 , marginHorizontal , 0 );
926985 }
0 commit comments