Skip to content

Commit

Permalink
[NavigationRail] Add item spacing attribute
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 639835301
  • Loading branch information
imhappi authored and pekingme committed Jun 5, 2024
1 parent abb6e91 commit 99e8044
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 5 deletions.
3 changes: 3 additions & 0 deletions docs/components/NavigationRail.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@ for more attributes.
**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))
**Label visibility mode** | `app:labelVisibilityMode` | `setLabelVisibilityMode`<br/>`getLabelVisibilityMode` | `LABEL_VISIBILITY_AUTO`
**Item minimum height** | `app:itemMinHeight` | `setItemMinimumHeight`<br/>`getItemMinimumHeight` | `NO_ITEM_MINIMUM_HEIGHT`
**Item spacing** | `app:itemSpacing` | `setItemSpacing`<br/>`getItemSpacing` | `0dp`

**Note:** If there's not enough room, `itemMinHeight` and `itemSpacing` may not be respected in order to fit the items.

#### Active indicator attributes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private void loadFromAttributes(@NonNull Context context, @Nullable AttributeSet
final TypedArray array =
context.getTheme().obtainStyledAttributes(attrs, R.styleable.FlowLayout, 0, 0);
lineSpacing = array.getDimensionPixelSize(R.styleable.FlowLayout_lineSpacing, 0);
itemSpacing = array.getDimensionPixelSize(R.styleable.FlowLayout_itemSpacing, 0);
itemSpacing = array.getDimensionPixelSize(R.styleable.FlowLayout_horizontalItemSpacing, 0);
array.recycle();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<!-- Do not expose publicly, FlowLayout (private class) that is the parent for ChipGroup (public), which has its own public spacing attributes. -->
<declare-styleable name="FlowLayout">
<!-- Horizontal spacing between two items being laid out. -->
<attr name="itemSpacing" format="dimension"/>
<attr name="horizontalItemSpacing" format="dimension"/>
<!-- Vertical Spacing between two lines of items being laid out. -->
<attr name="lineSpacing" format="dimension"/>
</declare-styleable>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
public class NavigationRailMenuView extends NavigationBarMenuView {

@Px private int itemMinimumHeight = NO_ITEM_MINIMUM_HEIGHT;
@Px private int itemSpacing = 0;
private final FrameLayout.LayoutParams layoutParams =
new FrameLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);

Expand Down Expand Up @@ -72,13 +73,26 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final int count = getChildCount();
final int width = right - left;
int visibleCount = 0;
int childrenHeight = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
childrenHeight += child.getMeasuredHeight();
visibleCount += 1;
}
}
int spacing =
visibleCount <= 1
? 0
: max(0, min((getMeasuredHeight() - childrenHeight) / (visibleCount - 1), itemSpacing));
int used = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
int childHeight = child.getMeasuredHeight();
child.layout(/* l= */ 0, used, width, childHeight + used);
used += childHeight;
used += childHeight + spacing;
}
}
}
Expand Down Expand Up @@ -129,15 +143,19 @@ private int measureSharedChildHeights(
}

int childCount = getChildCount();
int visibleChildCount = 0;
int totalHeight = 0;
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
if (child.getVisibility() == VISIBLE) {
visibleChildCount += 1;
}
if (child != selectedView) {
totalHeight += measureChildHeight(child, widthMeasureSpec, childHeightSpec);
}
}

return totalHeight;
return totalHeight + max(0, visibleChildCount - 1) * itemSpacing;
}

private int measureChildHeight(View child, int widthMeasureSpec, int heightMeasureSpec) {
Expand Down Expand Up @@ -172,6 +190,18 @@ public int getItemMinimumHeight() {
return this.itemMinimumHeight;
}

public void setItemSpacing(@Px int spacing) {
if (this.itemSpacing != spacing) {
this.itemSpacing = spacing;
requestLayout();
}
}

@Px
public int getItemSpacing() {
return this.itemSpacing;
}

boolean isTopGravity() {
return (layoutParams.gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.TOP;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ public NavigationRailView(
AnimationUtils.lerp(getItemPaddingBottom(), largeFontBottomPadding, progress);
setItemPaddingTop(Math.round(topPadding));
setItemPaddingBottom(Math.round(bottomPadding));
setItemSpacing(
attributes.getDimensionPixelSize(R.styleable.NavigationRailView_itemSpacing, 0));

attributes.recycle();

Expand Down Expand Up @@ -358,6 +360,20 @@ public void setItemMinimumHeight(@Px int minHeight) {
menuView.setItemMinimumHeight(minHeight);
}

/**
* Set the padding in between the navigation rail menu items.
*/
public void setItemSpacing(@Px int itemSpacing) {
getNavigationRailMenuView().setItemSpacing(itemSpacing);
}

/**
* Get the padding in between the navigation rail menu items.
*/
public int getItemSpacing() {
return getNavigationRailMenuView().getItemSpacing();
}

@Override
public int getMaxItemCount() {
return MAX_ITEM_COUNT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<public name="menuGravity" type="attr"/>
<public name="contentMarginTop" type="attr"/>
<public name="headerMarginBottom" type="attr"/>
<public name="itemSpacing" type="attr"/>
<public name="Widget.MaterialComponents.NavigationRailView" type="style"/>
<public name="Widget.MaterialComponents.NavigationRailView.Compact" type="style"/>
<public name="Widget.MaterialComponents.NavigationRailView.Colored" type="style"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
<attr name="headerMarginBottom" format="dimension"/>
<!-- The top margin of the content of the navigation rail. -->
<attr name="contentMarginTop" format="dimension"/>
<!-- Specifies how the navigation rail destinations should be aligned as a group. -->
<!-- The spacing between the navigation rail items. -->
<attr name="itemSpacing" format="dimension"/>

<!-- Specifies how the navigation rail destinations should be aligned as a group. -->
<attr name="menuGravity">
<!-- Navigation rail destinations will be aligned as a group at the top. This is the default behavior. -->
<!-- Gravity.TOP | Gravity.CENTER_HORIZONTAL-->
Expand Down

0 comments on commit 99e8044

Please sign in to comment.