Skip to content

Commit 8b016a0

Browse files
imhappihunterstich
authored andcommitted
[NavigationRail][Badge] Added bigger padding in between items on the navigation rail when font scale is large so there is more room for the badges when they are forced inside the view bounds
Also fixed bug with navigation rail items moving when there is a badge vs when there is no longer a badge, and adds 4dp padding between icon container/active indicator and label text as per specs https://m3.material.io/components/navigation-rail/overview PiperOrigin-RevId: 540349399
1 parent 45c8d42 commit 8b016a0

File tree

12 files changed

+102
-16
lines changed

12 files changed

+102
-16
lines changed

docs/components/NavigationRail.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,14 @@ for more attributes.
311311

312312
#### Active indicator attributes
313313

314-
**Element** | **Attribute** | **Related methods** | **Default value**
315-
--------------------- | ---------------------- | ------------------------------------------------------------------------------------- | -----------------
316-
**Color** | `android:color` | `setItemActiveIndicatorColor`<br/>`getItemActiveIndicatorColor` | `?attr/colorSecondaryContainer`
317-
**Width** | `android:width` | `setItemActiveIndicatorWidth`<br/>`getItemActiveIndicatorWidth` | `56dp`
318-
**Height** | `android:height` | `setItemActiveIndicatorHeight`<br/>`setItemActiveIndicatorHeight` | `32dp`
319-
**Shape** | `app:shapeAppearance` | `setItemActiveIndicatorShapeAppearance`<br/>`getItemActiveIndicatorShapeAppearance` | `50% rounded`
320-
**Margin horizontal** | `app:marginHorizontal` | `setItemActiveIndicatorMarginHorizontal`<br/>`getItemActiveIndicatorMarginHorizontal` | `4dp`
314+
**Element** | **Attribute** | **Related methods** | **Default value**
315+
--------------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------- | -----------------
316+
**Color** | `android:color` | `setItemActiveIndicatorColor`<br/>`getItemActiveIndicatorColor` | `?attr/colorSecondaryContainer`
317+
**Width** | `android:width` | `setItemActiveIndicatorWidth`<br/>`getItemActiveIndicatorWidth` | `56dp`
318+
**Height** | `android:height` | `setItemActiveIndicatorHeight`<br/>`setItemActiveIndicatorHeight` | `32dp`
319+
**Shape** | `app:shapeAppearance` | `setItemActiveIndicatorShapeAppearance`<br/>`getItemActiveIndicatorShapeAppearance` | `50% rounded`
320+
**Margin horizontal** | `app:marginHorizontal` | `setItemActiveIndicatorMarginHorizontal`<br/>`getItemActiveIndicatorMarginHorizontal` | `4dp`
321+
**Padding between indicator and label** | `app:activeIndicatorLabelPadding` | `setActiveIndicatorLabelPadding` <br/> `setActiveIndicatorLabelPadding` | `4dp`
321322

322323
#### Icon attributes
323324

lib/java/com/google/android/material/navigation/NavigationBarItemView.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public abstract class NavigationBarItemView extends FrameLayout implements MenuV
8787
@Nullable Drawable itemBackground;
8888
private int itemPaddingTop;
8989
private int itemPaddingBottom;
90+
private int activeIndicatorLabelPadding;
9091
private float shiftAmount;
9192
private float scaleUpFactor;
9293
private float scaleDownFactor;
@@ -146,6 +147,7 @@ public NavigationBarItemView(@NonNull Context context) {
146147

147148
itemPaddingTop = getResources().getDimensionPixelSize(getItemDefaultMarginResId());
148149
itemPaddingBottom = labelGroup.getPaddingBottom();
150+
activeIndicatorLabelPadding = getResources().getDimensionPixelSize(R.dimen.m3_navigation_item_active_indicator_label_padding);
149151

150152
// The labels used aren't always visible, so they are unreliable for accessibility. Instead,
151153
// the content description of the NavigationBarItemView should be used for accessibility.
@@ -190,6 +192,7 @@ protected int getSuggestedMinimumWidth() {
190192
protected int getSuggestedMinimumHeight() {
191193
LayoutParams labelGroupParams = (LayoutParams) labelGroup.getLayoutParams();
192194
return getSuggestedIconHeight()
195+
+ (labelGroup.getVisibility() == VISIBLE ? activeIndicatorLabelPadding : 0)
193196
+ labelGroupParams.topMargin
194197
+ labelGroup.getMeasuredHeight()
195198
+ labelGroupParams.bottomMargin;
@@ -785,6 +788,14 @@ public void setItemPaddingBottom(int paddingBottom) {
785788
}
786789
}
787790

791+
/** Set the padding between the active indicator container and the item label. */
792+
public void setActiveIndicatorLabelPadding(int activeIndicatorLabelPadding) {
793+
if (this.activeIndicatorLabelPadding != activeIndicatorLabelPadding) {
794+
this.activeIndicatorLabelPadding = activeIndicatorLabelPadding;
795+
refreshChecked();
796+
}
797+
}
798+
788799
/** Set whether or not this item should show an active indicator when checked. */
789800
public void setActiveIndicatorEnabled(boolean enabled) {
790801
this.activeIndicatorEnabled = enabled;
@@ -983,16 +994,9 @@ private int getSuggestedIconWidth() {
983994
}
984995

985996
private int getSuggestedIconHeight() {
986-
int badgeHeight = 0;
987-
if (badgeDrawable != null) {
988-
badgeHeight = badgeDrawable.getMinimumHeight() / 2;
989-
}
990-
991-
// Account for the fact that the badge may fit within the top margin. Bottom margin is ignored
992-
// because the icon view will be aligned to the baseline of the label group. But give space for
993-
// the badge at the bottom as well, so that icon does not move if badge gravity is changed.
994997
LayoutParams iconContainerParams = (LayoutParams) getIconOrContainer().getLayoutParams();
995-
return max(badgeHeight, iconContainerParams.topMargin) + icon.getMeasuredWidth() + badgeHeight;
998+
return iconContainerParams.topMargin
999+
+ getIconOrContainer().getMeasuredHeight();
9961000
}
9971001

9981002
/**

lib/java/com/google/android/material/navigation/NavigationBarMenuView.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ public abstract class NavigationBarMenuView extends ViewGroup implements MenuVie
9797
new SparseArray<>(ITEM_POOL_SIZE);
9898
private int itemPaddingTop = NO_PADDING;
9999
private int itemPaddingBottom = NO_PADDING;
100+
private int itemActiveIndicatorLabelPadding = NO_PADDING;
100101
private boolean itemActiveIndicatorEnabled;
101102
private int itemActiveIndicatorWidth;
102103
private int itemActiveIndicatorHeight;
@@ -366,6 +367,26 @@ public void setItemPaddingBottom(@Px int paddingBottom) {
366367
}
367368
}
368369

370+
/**
371+
* Get the distance between the item's active indicator container and the label.
372+
*/
373+
@Px
374+
public int getActiveIndicatorLabelPadding() {
375+
return itemActiveIndicatorLabelPadding;
376+
}
377+
378+
/**
379+
* Set the distance between the active indicator container and the item's label.
380+
*/
381+
public void setActiveIndicatorLabelPadding(@Px int activeIndicatorLabelPadding) {
382+
itemActiveIndicatorLabelPadding = activeIndicatorLabelPadding;
383+
if (buttons != null) {
384+
for (NavigationBarItemView item : buttons) {
385+
item.setActiveIndicatorLabelPadding(activeIndicatorLabelPadding);
386+
}
387+
}
388+
}
389+
369390
/**
370391
* Returns whether or not an active indicator is enabled for the navigation bar.
371392
*
@@ -733,6 +754,9 @@ public void buildMenuView() {
733754
if (itemPaddingBottom != NO_PADDING) {
734755
child.setItemPaddingBottom(itemPaddingBottom);
735756
}
757+
if (itemActiveIndicatorLabelPadding != NO_PADDING) {
758+
child.setActiveIndicatorLabelPadding(itemActiveIndicatorLabelPadding);
759+
}
736760
child.setActiveIndicatorWidth(itemActiveIndicatorWidth);
737761
child.setActiveIndicatorHeight(itemActiveIndicatorHeight);
738762
child.setActiveIndicatorMarginHorizontal(itemActiveIndicatorMarginHorizontal);

lib/java/com/google/android/material/navigation/NavigationBarView.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ public NavigationBarView(
211211
attributes.getDimensionPixelSize(R.styleable.NavigationBarView_itemPaddingBottom, 0));
212212
}
213213

214+
if (attributes.hasValue(R.styleable.NavigationBarView_activeIndicatorLabelPadding)) {
215+
setActiveIndicatorLabelPadding(
216+
attributes.getDimensionPixelSize(R.styleable.NavigationBarView_activeIndicatorLabelPadding, 0));
217+
}
218+
214219
if (attributes.hasValue(R.styleable.NavigationBarView_elevation)) {
215220
setElevation(attributes.getDimensionPixelSize(R.styleable.NavigationBarView_elevation, 0));
216221
}
@@ -575,6 +580,21 @@ public void setItemPaddingBottom(@Px int paddingBottom) {
575580
menuView.setItemPaddingBottom(paddingBottom);
576581
}
577582

583+
/**
584+
* Set the distance between the active indicator container and the item's label.
585+
*/
586+
public void setActiveIndicatorLabelPadding(@Px int activeIndicatorLabelPadding) {
587+
menuView.setActiveIndicatorLabelPadding(activeIndicatorLabelPadding);
588+
}
589+
590+
/**
591+
* Get the distance between the active indicator container and the item's label.
592+
*/
593+
@Px
594+
public int getActiveIndicatorLabelPadding() {
595+
return menuView.getActiveIndicatorLabelPadding();
596+
}
597+
578598
/**
579599
* Get whether or not a selected item should show an active indicator.
580600
*

lib/java/com/google/android/material/navigation/res-public/values/public.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
<public name="ThemeOverlay.Material3.NavigationView" type="style"/>
5252
<public name="Widget.Material3.DrawerLayout" type="style"/>
5353

54+
<public name="activeIndicatorLabelPadding" type="attr"/>
5455
<public name="itemPaddingTop" type="attr"/>
5556
<public name="itemPaddingBottom" type="attr"/>
5657
<public name="itemActiveIndicatorStyle" type="attr"/>

lib/java/com/google/android/material/navigation/res/values/attrs.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
<!-- The distance from the bottom of the label to the bottom of the navigation
7373
bar item.-->
7474
<attr name="itemPaddingBottom" format="dimension"/>
75+
<!-- Padding between the active indicator container and label. -->
76+
<attr name="activeIndicatorLabelPadding" format="dimension"/>
7577

7678
<!-- The style used for each navigation item's active indicator-->
7779
<attr name="itemActiveIndicatorStyle" format="reference"/>

lib/java/com/google/android/material/navigation/res/values/dimens.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@
4343
<dimen name="m3_navigation_menu_divider_horizontal_padding">28dp</dimen>
4444
<dimen name="m3_navigation_menu_headline_horizontal_padding">28dp</dimen>
4545
<dimen name="m3_navigation_drawer_layout_corner_size">16dp</dimen>
46+
<dimen name="m3_navigation_item_active_indicator_label_padding">4dp</dimen>
4647
</resources>
4748

lib/java/com/google/android/material/navigation/res/values/styles.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
<item name="subheaderInsetStart">@dimen/m3_navigation_menu_headline_horizontal_padding</item>
8181
<item name="subheaderInsetEnd">@dimen/m3_navigation_menu_headline_horizontal_padding</item>
8282
<item name="drawerLayoutCornerSize">@dimen/m3_navigation_drawer_layout_corner_size</item>
83+
<item name="activeIndicatorLabelPadding">@dimen/m3_navigation_item_active_indicator_label_padding</item>
8384
</style>
8485

8586
<style name="ShapeAppearanceOverlay.Material3.NavigationView.Item"

lib/java/com/google/android/material/navigationrail/NavigationRailView.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@
3838
import androidx.core.graphics.Insets;
3939
import androidx.core.view.ViewCompat;
4040
import androidx.core.view.WindowInsetsCompat;
41+
import com.google.android.material.animation.AnimationUtils;
4142
import com.google.android.material.internal.ThemeEnforcement;
4243
import com.google.android.material.internal.ViewUtils;
4344
import com.google.android.material.internal.ViewUtils.RelativePadding;
4445
import com.google.android.material.navigation.NavigationBarView;
46+
import com.google.android.material.resources.MaterialResources;
4547

4648
/**
4749
* Represents a standard navigation rail view for application. It is an implementation of <a
@@ -165,6 +167,21 @@ public NavigationRailView(
165167
R.styleable.NavigationRailView_paddingStartSystemWindowInsets, false);
166168
}
167169

170+
int largeFontTopPadding =
171+
getResources()
172+
.getDimensionPixelOffset(R.dimen.m3_navigation_rail_item_padding_top_with_large_font);
173+
int largeFontBottomPadding =
174+
getResources()
175+
.getDimensionPixelOffset(
176+
R.dimen.m3_navigation_rail_item_padding_bottom_with_large_font);
177+
float progress =
178+
AnimationUtils.lerp(0F, 1F, .3F, 1F, MaterialResources.getFontScale(context) - 1F);
179+
float topPadding = AnimationUtils.lerp(getItemPaddingTop(), largeFontTopPadding, progress);
180+
float bottomPadding =
181+
AnimationUtils.lerp(getItemPaddingBottom(), largeFontBottomPadding, progress);
182+
setItemPaddingTop(Math.round(topPadding));
183+
setItemPaddingBottom(Math.round(bottomPadding));
184+
168185
attributes.recycle();
169186

170187
applyWindowInsets();

lib/java/com/google/android/material/navigationrail/res/values/dimens.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@
3131
<dimen name="m3_navigation_rail_default_width">@dimen/m3_comp_navigation_rail_container_width</dimen>
3232
<dimen name="m3_navigation_rail_item_min_height">60dp</dimen>
3333
<dimen name="m3_navigation_rail_item_padding_top">4dp</dimen>
34+
<dimen name="m3_navigation_rail_item_padding_top_with_large_font">12dp</dimen>
35+
<dimen name="m3_navigation_rail_item_padding_bottom_with_large_font">16dp</dimen>
3436
<dimen name="m3_navigation_rail_item_padding_bottom">8dp</dimen>
3537
<dimen name="m3_navigation_rail_item_active_indicator_width">@dimen/m3_comp_navigation_rail_active_indicator_width</dimen>
3638
<dimen name="m3_navigation_rail_item_active_indicator_height">@dimen/m3_comp_navigation_rail_active_indicator_height</dimen>
3739
<dimen name="m3_navigation_rail_item_active_indicator_margin_horizontal">4dp</dimen>
40+
3841
</resources>

0 commit comments

Comments
 (0)