Skip to content

Commit 99e8044

Browse files
imhappipekingme
authored andcommitted
[NavigationRail] Add item spacing attribute
PiperOrigin-RevId: 639835301
1 parent abb6e91 commit 99e8044

File tree

7 files changed

+58
-5
lines changed

7 files changed

+58
-5
lines changed

docs/components/NavigationRail.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,9 @@ for more attributes.
322322
**Ripple (active)** | `app:itemRippleColor` | `setItemRippleColor`<br/>`getItemRippleColor` | `?attr/colorPrimary` at 12% (see all [states](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/navigation/res/color/mtrl_navigation_bar_ripple_color.xml))
323323
**Label visibility mode** | `app:labelVisibilityMode` | `setLabelVisibilityMode`<br/>`getLabelVisibilityMode` | `LABEL_VISIBILITY_AUTO`
324324
**Item minimum height** | `app:itemMinHeight` | `setItemMinimumHeight`<br/>`getItemMinimumHeight` | `NO_ITEM_MINIMUM_HEIGHT`
325+
**Item spacing** | `app:itemSpacing` | `setItemSpacing`<br/>`getItemSpacing` | `0dp`
326+
327+
**Note:** If there's not enough room, `itemMinHeight` and `itemSpacing` may not be respected in order to fit the items.
325328

326329
#### Active indicator attributes
327330

lib/java/com/google/android/material/internal/FlowLayout.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private void loadFromAttributes(@NonNull Context context, @Nullable AttributeSet
7070
final TypedArray array =
7171
context.getTheme().obtainStyledAttributes(attrs, R.styleable.FlowLayout, 0, 0);
7272
lineSpacing = array.getDimensionPixelSize(R.styleable.FlowLayout_lineSpacing, 0);
73-
itemSpacing = array.getDimensionPixelSize(R.styleable.FlowLayout_itemSpacing, 0);
73+
itemSpacing = array.getDimensionPixelSize(R.styleable.FlowLayout_horizontalItemSpacing, 0);
7474
array.recycle();
7575
}
7676

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
<!-- Do not expose publicly, FlowLayout (private class) that is the parent for ChipGroup (public), which has its own public spacing attributes. -->
4848
<declare-styleable name="FlowLayout">
4949
<!-- Horizontal spacing between two items being laid out. -->
50-
<attr name="itemSpacing" format="dimension"/>
50+
<attr name="horizontalItemSpacing" format="dimension"/>
5151
<!-- Vertical Spacing between two lines of items being laid out. -->
5252
<attr name="lineSpacing" format="dimension"/>
5353
</declare-styleable>

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

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
public class NavigationRailMenuView extends NavigationBarMenuView {
4040

4141
@Px private int itemMinimumHeight = NO_ITEM_MINIMUM_HEIGHT;
42+
@Px private int itemSpacing = 0;
4243
private final FrameLayout.LayoutParams layoutParams =
4344
new FrameLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
4445

@@ -72,13 +73,26 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
7273
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
7374
final int count = getChildCount();
7475
final int width = right - left;
76+
int visibleCount = 0;
77+
int childrenHeight = 0;
78+
for (int i = 0; i < count; i++) {
79+
final View child = getChildAt(i);
80+
if (child.getVisibility() != GONE) {
81+
childrenHeight += child.getMeasuredHeight();
82+
visibleCount += 1;
83+
}
84+
}
85+
int spacing =
86+
visibleCount <= 1
87+
? 0
88+
: max(0, min((getMeasuredHeight() - childrenHeight) / (visibleCount - 1), itemSpacing));
7589
int used = 0;
7690
for (int i = 0; i < count; i++) {
7791
final View child = getChildAt(i);
7892
if (child.getVisibility() != GONE) {
7993
int childHeight = child.getMeasuredHeight();
8094
child.layout(/* l= */ 0, used, width, childHeight + used);
81-
used += childHeight;
95+
used += childHeight + spacing;
8296
}
8397
}
8498
}
@@ -129,15 +143,19 @@ private int measureSharedChildHeights(
129143
}
130144

131145
int childCount = getChildCount();
146+
int visibleChildCount = 0;
132147
int totalHeight = 0;
133148
for (int i = 0; i < childCount; i++) {
134149
final View child = getChildAt(i);
150+
if (child.getVisibility() == VISIBLE) {
151+
visibleChildCount += 1;
152+
}
135153
if (child != selectedView) {
136154
totalHeight += measureChildHeight(child, widthMeasureSpec, childHeightSpec);
137155
}
138156
}
139157

140-
return totalHeight;
158+
return totalHeight + max(0, visibleChildCount - 1) * itemSpacing;
141159
}
142160

143161
private int measureChildHeight(View child, int widthMeasureSpec, int heightMeasureSpec) {
@@ -172,6 +190,18 @@ public int getItemMinimumHeight() {
172190
return this.itemMinimumHeight;
173191
}
174192

193+
public void setItemSpacing(@Px int spacing) {
194+
if (this.itemSpacing != spacing) {
195+
this.itemSpacing = spacing;
196+
requestLayout();
197+
}
198+
}
199+
200+
@Px
201+
public int getItemSpacing() {
202+
return this.itemSpacing;
203+
}
204+
175205
boolean isTopGravity() {
176206
return (layoutParams.gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.TOP;
177207
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ public NavigationRailView(
189189
AnimationUtils.lerp(getItemPaddingBottom(), largeFontBottomPadding, progress);
190190
setItemPaddingTop(Math.round(topPadding));
191191
setItemPaddingBottom(Math.round(bottomPadding));
192+
setItemSpacing(
193+
attributes.getDimensionPixelSize(R.styleable.NavigationRailView_itemSpacing, 0));
192194

193195
attributes.recycle();
194196

@@ -358,6 +360,20 @@ public void setItemMinimumHeight(@Px int minHeight) {
358360
menuView.setItemMinimumHeight(minHeight);
359361
}
360362

363+
/**
364+
* Set the padding in between the navigation rail menu items.
365+
*/
366+
public void setItemSpacing(@Px int itemSpacing) {
367+
getNavigationRailMenuView().setItemSpacing(itemSpacing);
368+
}
369+
370+
/**
371+
* Get the padding in between the navigation rail menu items.
372+
*/
373+
public int getItemSpacing() {
374+
return getNavigationRailMenuView().getItemSpacing();
375+
}
376+
361377
@Override
362378
public int getMaxItemCount() {
363379
return MAX_ITEM_COUNT;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<public name="menuGravity" type="attr"/>
2323
<public name="contentMarginTop" type="attr"/>
2424
<public name="headerMarginBottom" type="attr"/>
25+
<public name="itemSpacing" type="attr"/>
2526
<public name="Widget.MaterialComponents.NavigationRailView" type="style"/>
2627
<public name="Widget.MaterialComponents.NavigationRailView.Compact" type="style"/>
2728
<public name="Widget.MaterialComponents.NavigationRailView.Colored" type="style"/>

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
<attr name="headerMarginBottom" format="dimension"/>
2929
<!-- The top margin of the content of the navigation rail. -->
3030
<attr name="contentMarginTop" format="dimension"/>
31-
<!-- Specifies how the navigation rail destinations should be aligned as a group. -->
31+
<!-- The spacing between the navigation rail items. -->
32+
<attr name="itemSpacing" format="dimension"/>
33+
34+
<!-- Specifies how the navigation rail destinations should be aligned as a group. -->
3235
<attr name="menuGravity">
3336
<!-- Navigation rail destinations will be aligned as a group at the top. This is the default behavior. -->
3437
<!-- Gravity.TOP | Gravity.CENTER_HORIZONTAL-->

0 commit comments

Comments
 (0)