19
19
import com .google .android .material .R ;
20
20
21
21
import 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 ;
22
24
import static com .google .android .material .navigation .NavigationBarView .ITEM_ICON_GRAVITY_START ;
23
25
import static com .google .android .material .navigation .NavigationBarView .ITEM_ICON_GRAVITY_TOP ;
24
26
import static java .lang .Math .max ;
@@ -132,11 +134,14 @@ public abstract class NavigationBarItemView extends FrameLayout implements MenuV
132
134
// desired width.
133
135
private int activeIndicatorDesiredWidth = 0 ;
134
136
private int activeIndicatorDesiredHeight = 0 ;
137
+ private int activeIndicatorExpandedDesiredWidth = ACTIVE_INDICATOR_WIDTH_WRAP_CONTENT ;
138
+ private int activeIndicatorExpandedDesiredHeight = 0 ;
135
139
private boolean activeIndicatorResizeable = false ;
136
140
// The margin from the start and end of this view which the active indicator should respect. If
137
141
// the indicator width is greater than the total width minus the horizontal margins, the active
138
142
// indicator will assume the max width of the view's total width minus horizontal margins.
139
143
private int activeIndicatorMarginHorizontal = 0 ;
144
+ private int activeIndicatorExpandedMarginHorizontal = 0 ;
140
145
141
146
@ Nullable private BadgeDrawable badgeDrawable ;
142
147
@@ -169,6 +174,8 @@ public NavigationBarItemView(@NonNull Context context) {
169
174
largeLabel .setImportantForAccessibility (View .IMPORTANT_FOR_ACCESSIBILITY_NO );
170
175
setFocusable (true );
171
176
calculateTextScaleFactors (smallLabel .getTextSize (), largeLabel .getTextSize ());
177
+ activeIndicatorExpandedDesiredHeight = getResources ().getDimensionPixelSize (
178
+ R .dimen .m3_expressive_item_expanded_active_indicator_height_default );
172
179
173
180
// TODO(b/138148581): Support displaying a badge on label-only bottom navigation views.
174
181
innerContentContainer .addOnLayoutChangeListener (
@@ -178,7 +185,8 @@ public NavigationBarItemView(@NonNull Context context) {
178
185
}
179
186
// If item icon gravity is start, we want to update the active indicator width in a layout
180
187
// 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 ) {
182
190
LayoutParams lp = (LayoutParams ) innerContentContainer .getLayoutParams ();
183
191
int newWidth = right - left + lp .rightMargin + lp .leftMargin ;
184
192
LayoutParams indicatorParams = (LayoutParams ) activeIndicatorView .getLayoutParams ();
@@ -289,16 +297,18 @@ private void updateItemIconGravity() {
289
297
int labelGroupTopMargin = activeIndicatorLabelPadding ;
290
298
int labelGroupSideMargin = 0 ;
291
299
int sidePadding = 0 ;
300
+ int contentGravity = Gravity .CENTER ;
292
301
badgeFixedEdge = BadgeDrawable .BADGE_FIXED_EDGE_START ;
293
302
if (itemIconGravity == ITEM_ICON_GRAVITY_START ) {
294
303
gravity = Gravity .CENTER ;
304
+ contentGravity = Gravity .START | Gravity .CENTER_VERTICAL ;
295
305
sideMargin =
296
306
getResources ()
297
307
.getDimensionPixelSize (R .dimen .m3_expressive_navigation_item_leading_trailing_space );
298
308
labelGroupTopMargin = 0 ;
299
309
labelGroupSideMargin = activeIndicatorLabelPadding ;
300
310
badgeFixedEdge = BadgeDrawable .BADGE_FIXED_EDGE_END ;
301
- sidePadding = activeIndicatorMarginHorizontal ;
311
+ sidePadding = activeIndicatorExpandedMarginHorizontal ;
302
312
if (labelGroup .getParent () != innerContentContainer ) {
303
313
contentContainer .removeView (labelGroup );
304
314
innerContentContainer .addView (labelGroup );
@@ -313,6 +323,7 @@ private void updateItemIconGravity() {
313
323
(LayoutParams ) innerContentContainer .getLayoutParams ();
314
324
innerContentLp .leftMargin = sideMargin ;
315
325
innerContentLp .rightMargin = sideMargin ;
326
+ innerContentLp .gravity = contentGravity ;
316
327
LinearLayout .LayoutParams labelGroupLp =
317
328
(LinearLayout .LayoutParams ) labelGroup .getLayoutParams ();
318
329
labelGroupLp .rightMargin =
@@ -458,6 +469,13 @@ private void setLayoutConfigurationIconAndLabel(
458
469
itemIconGravity == ITEM_ICON_GRAVITY_TOP
459
470
? Gravity .CENTER_HORIZONTAL | Gravity .TOP
460
471
: 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 );
461
479
updateViewPaddingBottom (
462
480
labelGroup , itemIconGravity == ITEM_ICON_GRAVITY_TOP ? itemPaddingBottom : 0 );
463
481
labelGroup .setVisibility (VISIBLE );
@@ -467,6 +485,7 @@ private void setLayoutConfigurationIconAndLabel(
467
485
468
486
private void setLayoutConfigurationIconOnly () {
469
487
setViewMarginAndGravity (contentContainer , itemPaddingTop , itemPaddingTop , Gravity .CENTER );
488
+ setViewMarginAndGravity (innerContentContainer , 0 , 0 , Gravity .CENTER );
470
489
updateViewPaddingBottom (labelGroup , 0 );
471
490
labelGroup .setVisibility (GONE );
472
491
}
@@ -865,6 +884,28 @@ public void setActiveIndicatorWidth(int width) {
865
884
updateActiveIndicatorLayoutParams (getWidth ());
866
885
}
867
886
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
+
868
909
/**
869
910
* Update the active indicators width and height for the available width and label visibility
870
911
* mode.
@@ -882,10 +923,15 @@ private void updateActiveIndicatorLayoutParams(int availableWidth) {
882
923
min (activeIndicatorDesiredWidth , availableWidth - (activeIndicatorMarginHorizontal * 2 ));
883
924
int newHeight = activeIndicatorDesiredHeight ;
884
925
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 ;
889
935
}
890
936
LayoutParams indicatorParams = (LayoutParams ) activeIndicatorView .getLayoutParams ();
891
937
// If the label visibility is unlabeled, make the active indicator's height equal to its
@@ -921,6 +967,19 @@ public void setActiveIndicatorHeight(int height) {
921
967
*/
922
968
public void setActiveIndicatorMarginHorizontal (@ Px int marginHorizontal ) {
923
969
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 ;
924
983
if (itemIconGravity == ITEM_ICON_GRAVITY_START ) {
925
984
setPadding (marginHorizontal , 0 , marginHorizontal , 0 );
926
985
}
0 commit comments