Skip to content

Commit

Permalink
[NavigationRail] Add expanded state
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 660106312
  • Loading branch information
imhappi authored and drchen committed Aug 7, 2024
1 parent b34fff3 commit b36919f
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<attr name="android:background"/>
<!-- The initial expanded state for the AppBarLayout. This only takes effect when this
view is a direct child of a CoordinatorLayout. -->
<attr name="expanded" format="boolean"/>
<attr name="expanded" />
<attr name="android:keyboardNavigationCluster"/>
<attr name="android:touchscreenBlocksFocus"/>
<!-- Whether the {@link AppBarLayout} should lift on scroll. If set to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ public NavigationBarItemView(@NonNull Context context) {
// If item icon gravity is start, we want to update the active indicator width in a layout
// change listener to keep the active indicator size up to date with the content width.
if (itemIconGravity == ITEM_ICON_GRAVITY_START
&& activeIndicatorExpandedDesiredWidth == ACTIVE_INDICATOR_WIDTH_WRAP_CONTENT) {
&& activeIndicatorExpandedDesiredWidth == ACTIVE_INDICATOR_WIDTH_WRAP_CONTENT
&& (right - left) != (oldRight - oldLeft)) {
LayoutParams lp = (LayoutParams) innerContentContainer.getLayoutParams();
int newWidth = right - left + lp.rightMargin + lp.leftMargin;
LayoutParams indicatorParams = (LayoutParams) activeIndicatorView.getLayoutParams();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import static java.lang.Math.max;
import static java.lang.Math.min;

import android.content.Context;
Expand Down Expand Up @@ -109,11 +110,23 @@ public class NavigationRailView extends NavigationBarView {

private final int contentMarginTop;
private final int headerMarginBottom;
private final int minExpandedWidth;
private final int maxExpandedWidth;
@Nullable private View headerView;
@Nullable private Boolean paddingTopSystemWindowInsets = null;
@Nullable private Boolean paddingBottomSystemWindowInsets = null;
@Nullable private Boolean paddingStartSystemWindowInsets = null;

private boolean expanded = false;
private int collapsedItemSpacing;
private int collapsedItemMinHeight = NO_ITEM_MINIMUM_HEIGHT;
@ItemIconGravity private int collapsedIconGravity = ITEM_ICON_GRAVITY_TOP;
@ItemGravity private int collapsedItemGravity = ITEM_GRAVITY_TOP_CENTER;
private int expandedItemMinHeight;
@ItemIconGravity private int expandedIconGravity;
@ItemGravity private int expandedItemGravity;
private int expandedItemSpacing;

public NavigationRailView(@NonNull Context context) {
this(context, null);
}
Expand All @@ -133,6 +146,24 @@ public NavigationRailView(

// Ensure we are using the correctly themed context rather than the context that was passed in.
context = getContext();
minExpandedWidth =
getContext()
.getResources()
.getDimensionPixelSize(R.dimen.m3_navigation_rail_min_expanded_width);
maxExpandedWidth =
getContext()
.getResources()
.getDimensionPixelSize(R.dimen.m3_navigation_rail_max_expanded_width);
expandedItemSpacing =
getContext()
.getResources()
.getDimensionPixelSize(R.dimen.m3_navigation_rail_expanded_item_spacing);
expandedItemMinHeight =
getContext()
.getResources()
.getDimensionPixelSize(R.dimen.m3_navigation_rail_expanded_item_min_height);
expandedItemGravity = ITEM_GRAVITY_START_CENTER;
expandedIconGravity = ITEM_ICON_GRAVITY_START;

/* Custom attributes */
TintTypedArray attributes =
Expand All @@ -155,7 +186,7 @@ public NavigationRailView(
attributes.getInt(R.styleable.NavigationRailView_menuGravity, DEFAULT_MENU_GRAVITY));

if (attributes.hasValue(R.styleable.NavigationRailView_itemMinHeight)) {
setItemMinimumHeight(
setCollapsedItemMinimumHeight(
attributes.getDimensionPixelSize(
R.styleable.NavigationRailView_itemMinHeight, NO_ITEM_MINIMUM_HEIGHT));
}
Expand Down Expand Up @@ -189,14 +220,61 @@ public NavigationRailView(
AnimationUtils.lerp(getItemPaddingBottom(), largeFontBottomPadding, progress);
setItemPaddingTop(Math.round(topPadding));
setItemPaddingBottom(Math.round(bottomPadding));
setItemSpacing(
setCollapsedItemSpacing(
attributes.getDimensionPixelSize(R.styleable.NavigationRailView_itemSpacing, 0));

setExpanded(attributes.getBoolean(R.styleable.NavigationRailView_expanded, false));

attributes.recycle();

applyWindowInsets();
}

@Override
public void setItemIconGravity(int itemIconGravity) {
collapsedIconGravity = itemIconGravity;
expandedIconGravity = itemIconGravity;
super.setItemIconGravity(itemIconGravity);
}

@Override
public int getItemIconGravity() {
return getNavigationRailMenuView().getItemIconGravity();
}

@Override
public void setItemGravity(int itemGravity) {
collapsedItemGravity = itemGravity;
expandedItemGravity = itemGravity;
super.setItemGravity(itemGravity);
}

@Override
public int getItemGravity() {
return getNavigationRailMenuView().getItemGravity();
}

private void setExpanded(boolean expanded) {
if (this.expanded == expanded) {
return;
}
this.expanded = expanded;
int iconGravity = collapsedIconGravity;
int itemSpacing = collapsedItemSpacing;
int itemMinHeight = collapsedItemMinHeight;
int itemGravity = collapsedItemGravity;
if (expanded) {
iconGravity = expandedIconGravity;
itemSpacing = expandedItemSpacing;
itemMinHeight = expandedItemMinHeight;
itemGravity = expandedItemGravity;
}
getNavigationRailMenuView().setItemGravity(itemGravity);
super.setItemIconGravity(iconGravity);
getNavigationRailMenuView().setItemSpacing(itemSpacing);
getNavigationRailMenuView().setItemMinimumHeight(itemMinHeight);
}

private void applyWindowInsets() {
ViewUtils.doOnApplyWindowInsets(
this,
Expand Down Expand Up @@ -236,11 +314,28 @@ private boolean shouldApplyWindowInsetPadding(Boolean paddingInsetFlag) {
return paddingInsetFlag != null ? paddingInsetFlag : getFitsSystemWindows();
}

private int getMaxChildWidth() {
int childCount = getNavigationRailMenuView().getChildCount();
int maxChildWidth = 0;
for (int i = 0; i < childCount; i++) {
View child = getNavigationRailMenuView().getChildAt(i);
if (child.getVisibility() != GONE) {
maxChildWidth = max(maxChildWidth, child.getMeasuredWidth());
}
}
return maxChildWidth;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int minWidthSpec = makeMinWidthSpec(widthMeasureSpec);
if (expanded) {
// Try measuring child with no other restrictions than existing measure spec
measureChild(getNavigationRailMenuView(), widthMeasureSpec, heightMeasureSpec);
// Measure properly with the max child width
minWidthSpec = makeExpandedWidthMeasureSpec(widthMeasureSpec, getMaxChildWidth());
}
super.onMeasure(minWidthSpec, heightMeasureSpec);

if (isHeaderViewVisible()) {
int maxMenuHeight = getMeasuredHeight() - headerView.getMeasuredHeight() - contentMarginTop
- headerMarginBottom;
Expand Down Expand Up @@ -344,10 +439,9 @@ public int getMenuGravity() {
return getNavigationRailMenuView().getMenuGravity();
}

/** Get the minimum height each item in the navigation rail's menu should be. */
/** Get the current minimum height each item in the navigation rail's menu should be. */
public int getItemMinimumHeight() {
NavigationRailMenuView menuView = (NavigationRailMenuView) getMenuView();
return menuView.getItemMinimumHeight();
return getNavigationRailMenuView().getItemMinimumHeight();
}

/**
Expand All @@ -356,20 +450,38 @@ public int getItemMinimumHeight() {
* <p>If this is unset (-1), each item will be at least as tall as the navigation rail is wide.
*/
public void setItemMinimumHeight(@Px int minHeight) {
collapsedItemMinHeight = minHeight;
expandedItemMinHeight = minHeight;
NavigationRailMenuView menuView = (NavigationRailMenuView) getMenuView();
menuView.setItemMinimumHeight(minHeight);
}

// TODO: b/356407064 - Make public once expanded state is public
private void setCollapsedItemMinimumHeight(@Px int minHeight) {
collapsedItemMinHeight = minHeight;
if (!expanded) {
((NavigationRailMenuView) getMenuView()).setItemMinimumHeight(minHeight);
}
}

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

/**
* Get the padding in between the navigation rail menu items.
*/
// TODO: b/356407064 - Make public once expanded state is public
private void setCollapsedItemSpacing(@Px int itemSpacing) {
this.collapsedItemSpacing = itemSpacing;
if (!expanded) {
getNavigationRailMenuView().setItemSpacing(itemSpacing);
}
}

/** Get the current padding in between the navigation rail menu items. */
public int getItemSpacing() {
return getNavigationRailMenuView().getItemSpacing();
}
Expand Down Expand Up @@ -399,6 +511,17 @@ private int makeMinWidthSpec(int measureSpec) {
return MeasureSpec.makeMeasureSpec(
min(MeasureSpec.getSize(measureSpec), minWidth), MeasureSpec.EXACTLY);
}
return measureSpec;
}

private int makeExpandedWidthMeasureSpec(int measureSpec, int measuredWidth) {
int minWidth = min(minExpandedWidth, MeasureSpec.getSize(measureSpec));

if (MeasureSpec.getMode(measureSpec) != MeasureSpec.EXACTLY) {
int newWidth = max(measuredWidth, minWidth);
newWidth = max(getSuggestedMinimumWidth(), min(newWidth, maxExpandedWidth));
return MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY);
}

return measureSpec;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
<!-- Shape appearance overlay style reference for NavigationRail. To be used to augment
attributes declared in the shapeAppearance. Attribute declaration is in the Shape package. -->
<attr name="shapeAppearanceOverlay"/>
<!-- Whether or not to start the NavigationRailView in its expanded state. -->
<attr name="expanded" />
</declare-styleable>

</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,9 @@
<dimen name="m3_navigation_rail_expanded_active_indicator_height">56dp</dimen>
<dimen name="m3_navigation_rail_expanded_leading_trailing_space">20dp</dimen>

<dimen name="m3_navigation_rail_min_expanded_width">220dp</dimen>
<dimen name="m3_navigation_rail_max_expanded_width">360dp</dimen>
<dimen name="m3_navigation_rail_expanded_item_spacing">0dp</dimen>
<dimen name="m3_navigation_rail_expanded_item_min_height">56dp</dimen>

</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<attr name="ensureMinTouchTargetSize" format="boolean" />
<attr name="trackColor" format="color" />
<attr name="navigationIconTint" format="color"/>
<attr name="expanded" format="boolean" />

<!-- Navigation and Pickers -->
<attr name="headerLayout" format="reference"/>
Expand Down

0 comments on commit b36919f

Please sign in to comment.