Skip to content

Commit cfc307e

Browse files
committed
[NavigationView] fix navigation view item ripple
PiperOrigin-RevId: 434516655
1 parent 91c2530 commit cfc307e

File tree

6 files changed

+95
-6
lines changed

6 files changed

+95
-6
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import android.content.res.ColorStateList;
2525
import android.content.res.Resources;
2626
import android.graphics.drawable.Drawable;
27+
import android.graphics.drawable.RippleDrawable;
2728
import android.os.Bundle;
2829
import android.os.Parcelable;
2930
import androidx.appcompat.view.menu.MenuBuilder;
@@ -80,6 +81,7 @@ public class NavigationMenuPresenter implements MenuPresenter {
8081
ColorStateList textColor;
8182
ColorStateList iconTintList;
8283
Drawable itemBackground;
84+
RippleDrawable itemForeground;
8385
int itemHorizontalPadding;
8486
@Px int itemVerticalPadding;
8587
int itemIconPadding;
@@ -300,6 +302,11 @@ public void setItemBackground(@Nullable Drawable itemBackground) {
300302
updateMenuView(false);
301303
}
302304

305+
public void setItemForeground(@Nullable RippleDrawable itemForeground) {
306+
this.itemForeground = itemForeground;
307+
updateMenuView(false);
308+
}
309+
303310
public int getItemHorizontalPadding() {
304311
return itemHorizontalPadding;
305312
}
@@ -573,6 +580,9 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
573580
ViewCompat.setBackground(
574581
itemView,
575582
itemBackground != null ? itemBackground.getConstantState().newDrawable() : null);
583+
if (itemForeground != null) {
584+
itemView.setForeground(itemForeground.getConstantState().newDrawable());
585+
}
576586
NavigationMenuTextItem item = (NavigationMenuTextItem) items.get(position);
577587
itemView.setNeedsEmptyIcon(item.needsEmptyIcon);
578588
itemView.setPadding(

lib/java/com/google/android/material/internal/res/layout/design_navigation_item.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@
2424
android:paddingRight="?attr/listPreferredItemPaddingRight"
2525
android:focusable="true"
2626
android:foreground="?attr/selectableItemBackground"
27+
android:defaultFocusHighlightEnabled="false"
2728
tools:ignore="UnusedAttribute"/>

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

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import android.graphics.drawable.ColorDrawable;
3232
import android.graphics.drawable.Drawable;
3333
import android.graphics.drawable.InsetDrawable;
34+
import android.graphics.drawable.RippleDrawable;
3435
import android.os.Build;
3536
import android.os.Build.VERSION;
3637
import android.os.Build.VERSION_CODES;
@@ -72,6 +73,7 @@
7273
import com.google.android.material.internal.ScrimInsetsFrameLayout;
7374
import com.google.android.material.internal.ThemeEnforcement;
7475
import com.google.android.material.resources.MaterialResources;
76+
import com.google.android.material.ripple.RippleUtils;
7577
import com.google.android.material.shape.MaterialShapeDrawable;
7678
import com.google.android.material.shape.MaterialShapeUtils;
7779
import com.google.android.material.shape.ShapeAppearanceModel;
@@ -236,6 +238,21 @@ public NavigationView(@NonNull Context context, @Nullable AttributeSet attrs, in
236238
// appearance.
237239
if (itemBackground == null && hasShapeAppearance(a)) {
238240
itemBackground = createDefaultItemBackground(a);
241+
242+
ColorStateList itemRippleColor = MaterialResources.getColorStateList(
243+
context, a, R.styleable.NavigationView_itemRippleColor);
244+
245+
// Use a ripple matching the item's shape as the foreground for api level 21+ and if a ripple
246+
// color is set. Otherwise the selectableItemBackground foreground from the item layout will
247+
// be used
248+
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP && itemRippleColor != null) {
249+
Drawable itemRippleMask = createDefaultItemDrawable(a, null);
250+
RippleDrawable ripple = new RippleDrawable(
251+
RippleUtils.sanitizeRippleDrawableColor(itemRippleColor),
252+
null,
253+
itemRippleMask);
254+
presenter.setItemForeground(ripple);
255+
}
239256
}
240257

241258
if (a.hasValue(R.styleable.NavigationView_itemHorizontalPadding)) {
@@ -403,18 +420,24 @@ public void setElevation(float elevation) {
403420
* @param a The TintTypedArray containing the resolved NavigationView style attributes.
404421
*/
405422
@NonNull
406-
private final Drawable createDefaultItemBackground(@NonNull TintTypedArray a) {
423+
private Drawable createDefaultItemBackground(@NonNull TintTypedArray a) {
424+
ColorStateList fillColor = MaterialResources.getColorStateList(
425+
getContext(), a, R.styleable.NavigationView_itemShapeFillColor);
426+
return createDefaultItemDrawable(a, fillColor);
427+
}
428+
429+
@NonNull
430+
private Drawable createDefaultItemDrawable(
431+
@NonNull TintTypedArray a, @Nullable ColorStateList fillColor) {
407432
int shapeAppearanceResId = a.getResourceId(R.styleable.NavigationView_itemShapeAppearance, 0);
408433
int shapeAppearanceOverlayResId =
409434
a.getResourceId(R.styleable.NavigationView_itemShapeAppearanceOverlay, 0);
410435
MaterialShapeDrawable materialShapeDrawable =
411436
new MaterialShapeDrawable(
412437
ShapeAppearanceModel.builder(
413-
getContext(), shapeAppearanceResId, shapeAppearanceOverlayResId)
438+
getContext(), shapeAppearanceResId, shapeAppearanceOverlayResId)
414439
.build());
415-
materialShapeDrawable.setFillColor(
416-
MaterialResources.getColorStateList(
417-
getContext(), a, R.styleable.NavigationView_itemShapeFillColor));
440+
materialShapeDrawable.setFillColor(fillColor);
418441

419442
int insetLeft = a.getDimensionPixelSize(R.styleable.NavigationView_itemShapeInsetStart, 0);
420443
int insetTop = a.getDimensionPixelSize(R.styleable.NavigationView_itemShapeInsetTop, 0);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2022 The Android Open Source Project
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<selector xmlns:android="http://schemas.android.com/apk/res/android">
18+
19+
<!-- Selected -->
20+
21+
<!-- Uses the primary state layer since tapping a selected item keeps it
22+
selected. -->
23+
<item android:alpha="@dimen/m3_ripple_pressed_alpha"
24+
android:color="?attr/colorPrimary"
25+
android:state_pressed="true" android:state_selected="true"/>
26+
<item android:alpha="@dimen/m3_ripple_focused_alpha"
27+
android:color="?attr/colorOnSecondaryContainer"
28+
android:state_focused="true" android:state_selected="true"/>
29+
<item android:alpha="@dimen/m3_ripple_hovered_alpha"
30+
android:color="?attr/colorOnSecondaryContainer"
31+
android:state_hovered="true" android:state_selected="true"/>
32+
<item android:alpha="@dimen/m3_ripple_default_alpha"
33+
android:color="?attr/colorPrimary"
34+
android:state_selected="true"/>
35+
36+
<!-- Not selected -->
37+
38+
<!-- Uses the primary state layer since tapping an non-selected item will
39+
select it. -->
40+
<item android:alpha="@dimen/m3_ripple_selectable_pressed_alpha"
41+
android:color="?attr/colorPrimary"
42+
android:state_pressed="true"/>
43+
<item android:alpha="@dimen/m3_ripple_focused_alpha"
44+
android:color="?attr/colorOnSurface"
45+
android:state_focused="true"/>
46+
<item android:alpha="@dimen/m3_ripple_hovered_alpha"
47+
android:color="?attr/colorOnSurface"
48+
android:state_hovered="true"/>
49+
<item android:alpha="@dimen/m3_ripple_default_alpha"
50+
android:color="?attr/colorOnSurfaceVariant"/>
51+
52+
</selector>

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
~ limitations under the License.
1616
-->
1717
<resources>
18+
<attr name="itemRippleColor" format="color"/>
1819
<attr name="navigationViewStyle" format="reference"/>
1920

2021
<declare-styleable name="NavigationBarView">
@@ -43,7 +44,7 @@
4344
<!-- The ColorStateList to use for a ripple background. This only exists because creating
4445
ripples in drawable xml based on theme colors is not supported pre-23. This will be ignored
4546
if itemBackground is set.-->
46-
<attr name="itemRippleColor" format="color"/>
47+
<attr name="itemRippleColor"/>
4748
<!-- The size to provide for the navigation item icons. -->
4849
<attr name="itemIconSize"/>
4950
<!-- The tint to apply to the navigation item icons. Attribute type definition is in navigation
@@ -104,6 +105,7 @@
104105
<!-- A background drawable to use for navigation items. If this is set, this overrides the
105106
default background drawable for items and the itemShape* attributes will be ignored -->
106107
<attr name="itemBackground" format="reference"/>
108+
<attr name="itemRippleColor"/>
107109
<attr name="itemTextAppearance" format="reference"/>
108110
<!-- Layout resource to inflate as the header -->
109111
<attr name="headerLayout"/>

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
@@ -67,6 +67,7 @@
6767
<item name="itemVerticalPadding">@dimen/m3_navigation_item_vertical_padding</item>
6868
<item name="itemTextAppearance">?attr/textAppearanceLabelLarge</item>
6969
<item name="itemIconTint">@color/m3_navigation_item_icon_tint</item>
70+
<item name="itemRippleColor">@color/m3_navigation_item_ripple_color</item>
7071
<item name="itemShapeFillColor">@color/m3_navigation_item_background_color</item>
7172
<item name="itemTextColor">@color/m3_navigation_item_text_color</item>
7273
<item name="topInsetScrimEnabled">false</item>

0 commit comments

Comments
 (0)