Skip to content

Commit 644909b

Browse files
committed
[NavigationView] Fix behavior of itemShapeInset* attributes
Resolves material-components#4473 Resolves material-components#4474
1 parent de33cee commit 644909b

1 file changed

Lines changed: 103 additions & 61 deletions

File tree

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

Lines changed: 103 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,23 @@ public class NavigationView extends ScrimInsetsFrameLayout implements MaterialBa
147147
private boolean startInsetScrimEnabled = true;
148148
private boolean endInsetScrimEnabled = true;
149149

150+
@Nullable private Drawable itemBackground;
151+
@Nullable private ShapeAppearanceModel itemShapeAppearanceModel;
152+
153+
private int itemShapeInsetStart;
154+
private int itemShapeInsetTop;
155+
private int itemShapeInsetEnd;
156+
private int itemShapeInsetBottom;
157+
private int itemShapeInsetLeft;
158+
private int itemShapeInsetRight;
159+
160+
@Nullable private ColorStateList itemShapeFillColor;
161+
@Nullable private ColorStateList itemRippleColor;
162+
150163
@Px private int drawerLayoutCornerSize = 0;
151164
private final boolean drawerLayoutCornerSizeBackAnimationEnabled;
152165
@Px private final int drawerLayoutCornerSizeBackAnimationMax;
153166
private final ShapeableDelegate shapeableDelegate = ShapeableDelegate.create(this);
154-
@Nullable private ShapeAppearanceModel itemShapeAppearanceModel;
155167

156168
private final MaterialSideContainerBackHelper sideContainerBackHelper =
157169
new MaterialSideContainerBackHelper(this);
@@ -280,30 +292,7 @@ public NavigationView(@NonNull Context context, @Nullable AttributeSet attrs, in
280292
itemTextColor = createDefaultColorStateList(android.R.attr.textColorPrimary);
281293
}
282294

283-
Drawable itemBackground = a.getDrawable(R.styleable.NavigationView_itemBackground);
284-
// Set a shaped itemBackground if itemBackground hasn't been set and there is a shape
285-
// appearance.
286-
if (itemBackground == null && hasShapeAppearance(a)) {
287-
itemBackground = createDefaultItemBackground(a);
288-
289-
ColorStateList itemRippleColor =
290-
MaterialResources.getColorStateList(
291-
context, a, R.styleable.NavigationView_itemRippleColor);
292-
293-
// Use a ripple matching the item's shape as the foreground if a ripple color is set.
294-
// Otherwise the selectableItemBackground foreground from the item layout will be used.
295-
if (itemRippleColor != null) {
296-
Drawable itemRippleMask = createDefaultItemDrawable(a, null);
297-
RippleDrawable ripple =
298-
new RippleDrawable(
299-
RippleUtils.sanitizeRippleDrawableColor(itemRippleColor), null, itemRippleMask);
300-
FocusRingDrawable focusRingDrawable = FocusRingDrawable.layer(context, ripple);
301-
if (focusRingDrawable != null) {
302-
focusRingDrawable.setFocusRingShapeAppearance(itemShapeAppearanceModel);
303-
}
304-
presenter.setItemForeground(ripple);
305-
}
306-
}
295+
initItemBackgrounds(context, a);
307296

308297
if (a.hasValue(R.styleable.NavigationView_itemHorizontalPadding)) {
309298
final int itemHorizontalPadding =
@@ -372,7 +361,6 @@ public void onMenuModeChange(MenuBuilder menu) {}
372361
}
373362
presenter.setItemTextAppearanceActiveBoldEnabled(textAppearanceActiveBoldEnabled);
374363
presenter.setItemTextColor(itemTextColor);
375-
presenter.setItemBackground(itemBackground);
376364
presenter.setItemIconPadding(itemIconPadding);
377365
this.menu.addMenuPresenter(presenter);
378366
addView((View) presenter.getMenuView(this));
@@ -390,6 +378,95 @@ public void onMenuModeChange(MenuBuilder menu) {}
390378
setupInsetScrimsListener();
391379
}
392380

381+
private void initItemBackgrounds(@NonNull Context context, @NonNull TintTypedArray a) {
382+
itemBackground = a.getDrawable(R.styleable.NavigationView_itemBackground);
383+
if (itemBackground == null && hasShapeAppearance(a)) {
384+
int shapeAppearanceResId = a.getResourceId(R.styleable.NavigationView_itemShapeAppearance, 0);
385+
int shapeAppearanceOverlayResId = a.getResourceId(R.styleable.NavigationView_itemShapeAppearanceOverlay, 0);
386+
387+
itemShapeAppearanceModel = ShapeAppearanceModel
388+
.builder(context, shapeAppearanceResId, shapeAppearanceOverlayResId)
389+
.build();
390+
391+
itemShapeInsetStart = a.getDimensionPixelSize(R.styleable.NavigationView_itemShapeInsetStart, 0);
392+
itemShapeInsetTop = a.getDimensionPixelSize(R.styleable.NavigationView_itemShapeInsetTop, 0);
393+
itemShapeInsetEnd = a.getDimensionPixelSize(R.styleable.NavigationView_itemShapeInsetEnd, 0);
394+
itemShapeInsetBottom = a.getDimensionPixelSize(R.styleable.NavigationView_itemShapeInsetBottom, 0);
395+
396+
itemShapeFillColor = MaterialResources.getColorStateList(context, a, R.styleable.NavigationView_itemShapeFillColor);
397+
itemRippleColor = MaterialResources.getColorStateList(context, a, R.styleable.NavigationView_itemRippleColor);
398+
}
399+
400+
updateItemShapeInsets();
401+
updateItemBackground();
402+
updateItemForeground();
403+
}
404+
405+
private void updateItemShapeInsets() {
406+
final int layoutDirection = getLayoutDirection();
407+
itemShapeInsetLeft = layoutDirection == View.LAYOUT_DIRECTION_LTR
408+
? itemShapeInsetStart
409+
: itemShapeInsetEnd;
410+
411+
itemShapeInsetRight = layoutDirection == View.LAYOUT_DIRECTION_LTR
412+
? itemShapeInsetEnd
413+
: itemShapeInsetStart;
414+
}
415+
416+
private void updateItemBackground() {
417+
if (itemBackground != null) {
418+
presenter.setItemBackground(itemBackground);
419+
} else if (itemShapeAppearanceModel != null) {
420+
final MaterialShapeDrawable itemShapeDrawable = new MaterialShapeDrawable(itemShapeAppearanceModel);
421+
itemShapeDrawable.setFillColor(itemShapeFillColor);
422+
423+
final InsetDrawable itemDrawable = new InsetDrawable(
424+
itemShapeDrawable,
425+
itemShapeInsetLeft,
426+
itemShapeInsetTop,
427+
itemShapeInsetRight,
428+
itemShapeInsetBottom);
429+
430+
presenter.setItemBackground(itemDrawable);
431+
} else {
432+
presenter.setItemBackground(null);
433+
}
434+
}
435+
436+
private void updateItemForeground() {
437+
if (itemShapeAppearanceModel != null) {
438+
final MaterialShapeDrawable itemShapeDrawable = new MaterialShapeDrawable(itemShapeAppearanceModel);
439+
final InsetDrawable itemRippleMaskDrawable = new InsetDrawable(
440+
itemShapeDrawable,
441+
itemShapeInsetLeft,
442+
itemShapeInsetTop,
443+
itemShapeInsetRight,
444+
itemShapeInsetBottom);
445+
446+
final RippleDrawable itemRippleDrawable = new RippleDrawable(
447+
RippleUtils.sanitizeRippleDrawableColor(itemRippleColor), null, itemRippleMaskDrawable);
448+
449+
final FocusRingDrawable itemFocusRingDrawable =
450+
FocusRingDrawable.layer(getContext(), itemRippleDrawable);
451+
452+
if (itemFocusRingDrawable != null) {
453+
itemFocusRingDrawable.setFocusRingShapeAppearance(itemShapeAppearanceModel);
454+
}
455+
456+
presenter.setItemForeground(itemRippleDrawable);
457+
} else {
458+
presenter.setItemForeground(null);
459+
}
460+
}
461+
462+
@Override
463+
public void onRtlPropertiesChanged(int layoutDirection) {
464+
super.onRtlPropertiesChanged(layoutDirection);
465+
updateItemShapeInsets();
466+
updateItemBackground();
467+
updateItemForeground();
468+
}
469+
393470
@Override
394471
public void setOverScrollMode(int overScrollMode) {
395472
super.setOverScrollMode(overScrollMode);
@@ -515,41 +592,6 @@ public void setElevation(float elevation) {
515592
MaterialShapeUtils.setElevation(this, elevation);
516593
}
517594

518-
/**
519-
* Creates a {@link MaterialShapeDrawable} to use as the {@code itemBackground} and wraps it in an
520-
* {@link InsetDrawable} for margins.
521-
*
522-
* @param a The TintTypedArray containing the resolved NavigationView style attributes.
523-
*/
524-
@NonNull
525-
private Drawable createDefaultItemBackground(@NonNull TintTypedArray a) {
526-
ColorStateList fillColor =
527-
MaterialResources.getColorStateList(
528-
getContext(), a, R.styleable.NavigationView_itemShapeFillColor);
529-
return createDefaultItemDrawable(a, fillColor);
530-
}
531-
532-
@NonNull
533-
private Drawable createDefaultItemDrawable(
534-
@NonNull TintTypedArray a, @Nullable ColorStateList fillColor) {
535-
int shapeAppearanceResId = a.getResourceId(R.styleable.NavigationView_itemShapeAppearance, 0);
536-
int shapeAppearanceOverlayResId =
537-
a.getResourceId(R.styleable.NavigationView_itemShapeAppearanceOverlay, 0);
538-
itemShapeAppearanceModel =
539-
ShapeAppearanceModel.builder(
540-
getContext(), shapeAppearanceResId, shapeAppearanceOverlayResId)
541-
.build();
542-
MaterialShapeDrawable materialShapeDrawable =
543-
new MaterialShapeDrawable(itemShapeAppearanceModel);
544-
materialShapeDrawable.setFillColor(fillColor);
545-
546-
int insetLeft = a.getDimensionPixelSize(R.styleable.NavigationView_itemShapeInsetStart, 0);
547-
int insetTop = a.getDimensionPixelSize(R.styleable.NavigationView_itemShapeInsetTop, 0);
548-
int insetRight = a.getDimensionPixelSize(R.styleable.NavigationView_itemShapeInsetEnd, 0);
549-
int insetBottom = a.getDimensionPixelSize(R.styleable.NavigationView_itemShapeInsetBottom, 0);
550-
return new InsetDrawable(materialShapeDrawable, insetLeft, insetTop, insetRight, insetBottom);
551-
}
552-
553595
@Override
554596
protected Parcelable onSaveInstanceState() {
555597
Parcelable superState = super.onSaveInstanceState();

0 commit comments

Comments
 (0)