@@ -166,6 +166,7 @@ public abstract class NavigationBarItemView extends FrameLayout
166
166
private boolean expanded = false ;
167
167
private boolean onlyShowWhenExpanded = false ;
168
168
private boolean measurePaddingFromBaseline = false ;
169
+ private boolean scaleLabelSizeWithFont = false ;
169
170
170
171
public NavigationBarItemView (@ NonNull Context context ) {
171
172
super (context );
@@ -208,20 +209,37 @@ public NavigationBarItemView(@NonNull Context context) {
208
209
if (icon .getVisibility () == VISIBLE ) {
209
210
tryUpdateBadgeBounds (icon );
210
211
}
211
- // If item icon gravity is start, we want to update the active indicator width in a layout
212
- // change listener to keep the active indicator size up to date with the content width.
213
212
LayoutParams lp = (LayoutParams ) innerContentContainer .getLayoutParams ();
214
213
int newWidth = right - left + lp .rightMargin + lp .leftMargin ;
214
+ int newHeight = bottom - top + lp .topMargin + lp .bottomMargin ;
215
+ // If item icon gravity is start, we want to update the active indicator width in a layout
216
+ // change listener to keep the active indicator size up to date with the content width.
215
217
if (itemIconGravity == ITEM_ICON_GRAVITY_START
216
- && activeIndicatorExpandedDesiredWidth == ACTIVE_INDICATOR_WIDTH_WRAP_CONTENT
217
- && newWidth != activeIndicatorView . getMeasuredWidth ()) {
218
+ && activeIndicatorExpandedDesiredWidth == ACTIVE_INDICATOR_WIDTH_WRAP_CONTENT ) {
219
+
218
220
LayoutParams indicatorParams = (LayoutParams ) activeIndicatorView .getLayoutParams ();
219
- int minWidth =
220
- min (
221
- activeIndicatorDesiredWidth ,
222
- getMeasuredWidth () - (activeIndicatorMarginHorizontal * 2 ));
223
- indicatorParams .width = max (newWidth , minWidth );
224
- activeIndicatorView .setLayoutParams (indicatorParams );
221
+ boolean layoutParamsChanged = false ;
222
+ if (activeIndicatorExpandedDesiredWidth == ACTIVE_INDICATOR_WIDTH_WRAP_CONTENT
223
+ && activeIndicatorView .getMeasuredWidth () != newWidth ) {
224
+ int minWidth =
225
+ min (
226
+ activeIndicatorDesiredWidth ,
227
+ getMeasuredWidth () - (activeIndicatorMarginHorizontal * 2 ));
228
+ indicatorParams .width = max (newWidth , minWidth );
229
+ layoutParamsChanged = true ;
230
+ }
231
+
232
+ // We expect the active indicator height to be larger than the height of the
233
+ // inner content due to having a min height, but if it is smaller (for example due to
234
+ // the text content changing to be multi-line) it should encompass that
235
+ if (activeIndicatorView .getMeasuredHeight () < newHeight ) {
236
+ indicatorParams .height = newHeight ;
237
+ layoutParamsChanged = true ;
238
+ }
239
+
240
+ if (layoutParamsChanged ) {
241
+ activeIndicatorView .setLayoutParams (indicatorParams );
242
+ }
225
243
}
226
244
});
227
245
}
@@ -819,12 +837,28 @@ public void setMeasureBottomPaddingFromLabelBaseline(boolean measurePaddingFromB
819
837
requestLayout ();
820
838
}
821
839
840
+ public void setLabelFontScalingEnabled (boolean scaleLabelSizeWithFont ) {
841
+ this .scaleLabelSizeWithFont = scaleLabelSizeWithFont ;
842
+ setTextAppearanceActive (textAppearanceActive );
843
+ setTextAppearanceInactive (textAppearanceInactive );
844
+ setHorizontalTextAppearanceActive (horizontalTextAppearanceActive );
845
+ setHorizontalTextAppearanceInactive (horizontalTextAppearanceInactive );
846
+ }
847
+
848
+ private void setTextAppearanceForLabel (TextView label , int textAppearance ) {
849
+ if (scaleLabelSizeWithFont ) {
850
+ TextViewCompat .setTextAppearance (label , textAppearance );
851
+ } else {
852
+ setTextAppearanceWithoutFontScaling (label , textAppearance );
853
+ }
854
+ }
855
+
822
856
private void updateInactiveLabelTextAppearance (
823
857
@ Nullable TextView smallLabel , @ StyleRes int textAppearanceInactive ) {
824
858
if (smallLabel == null ) {
825
859
return ;
826
860
}
827
- setTextAppearanceWithoutFontScaling (smallLabel , textAppearanceInactive );
861
+ setTextAppearanceForLabel (smallLabel , textAppearanceInactive );
828
862
calculateTextScaleFactors ();
829
863
smallLabel .setMinimumHeight (
830
864
MaterialResources .getUnscaledLineHeight (
@@ -841,7 +875,7 @@ private void updateActiveLabelTextAppearance(
841
875
if (largeLabel == null ) {
842
876
return ;
843
877
}
844
- setTextAppearanceWithoutFontScaling (largeLabel , textAppearanceActive );
878
+ setTextAppearanceForLabel (largeLabel , textAppearanceActive );
845
879
calculateTextScaleFactors ();
846
880
largeLabel .setMinimumHeight (
847
881
MaterialResources .getUnscaledLineHeight (
@@ -911,6 +945,37 @@ private static void setTextAppearanceWithoutFontScaling(
911
945
}
912
946
}
913
947
948
+ public void setLabelMaxLines (int labelMaxLines ) {
949
+ smallLabel .setMaxLines (labelMaxLines );
950
+ largeLabel .setMaxLines (labelMaxLines );
951
+ expandedSmallLabel .setMaxLines (labelMaxLines );
952
+ expandedLargeLabel .setMaxLines (labelMaxLines );
953
+
954
+ // Due to b/316260445 that was fixed in V+, text with ellipses may be cut off when centered
955
+ // due to letter spacing being miscalculated for the ellipses character. We only center the text
956
+ // in the following scenarios:
957
+ // 1. API level is greater than 34, OR
958
+ // 2. The text is not cut off by an ellipses
959
+ if (VERSION .SDK_INT > VERSION_CODES .UPSIDE_DOWN_CAKE ) {
960
+ smallLabel .setGravity (Gravity .CENTER );
961
+ largeLabel .setGravity (Gravity .CENTER );
962
+ } else if (labelMaxLines > 1 ) {
963
+ // If not single-line, remove the ellipses and center. Removing the ellipses is an unfortunate
964
+ // tradeoff due to this bug. We do not want to remove the ellipses for single-line text
965
+ // because centering text is not useful (since the textview is centered already) and we
966
+ // would rather keep the ellipses.
967
+ smallLabel .setEllipsize (null );
968
+ largeLabel .setEllipsize (null );
969
+ smallLabel .setGravity (Gravity .CENTER );
970
+ largeLabel .setGravity (Gravity .CENTER );
971
+ } else {
972
+ smallLabel .setGravity (Gravity .CENTER_VERTICAL );
973
+ largeLabel .setGravity (Gravity .CENTER_VERTICAL );
974
+ }
975
+
976
+ requestLayout ();
977
+ }
978
+
914
979
public void setTextColor (@ Nullable ColorStateList color ) {
915
980
textColor = color ;
916
981
if (color != null ) {
@@ -1133,7 +1198,8 @@ private void updateActiveIndicatorLayoutParams(int availableWidth) {
1133
1198
} else {
1134
1199
newWidth = min (activeIndicatorExpandedDesiredWidth , adjustedAvailableWidth );
1135
1200
}
1136
- newHeight = activeIndicatorExpandedDesiredHeight ;
1201
+ newHeight =
1202
+ max (activeIndicatorExpandedDesiredHeight , innerContentContainer .getMeasuredHeight ());
1137
1203
}
1138
1204
LayoutParams indicatorParams = (LayoutParams ) activeIndicatorView .getLayoutParams ();
1139
1205
// If the label visibility is unlabeled, make the active indicator's height equal to its
0 commit comments