Skip to content

Commit 6c3b510

Browse files
ikim24afohrman
authored andcommitted
Adds itemRippleColor attribute to the BottomNavigationView as an alternative for itemBackground to support using ripples based on theme attributes pre-23. And update BottomNavigationView ripples to match TabLayout ripples.
PiperOrigin-RevId: 235237859
1 parent b7f520d commit 6c3b510

File tree

5 files changed

+138
-1
lines changed

5 files changed

+138
-1
lines changed

lib/java/com/google/android/material/bottomnavigation/BottomNavigationView.java

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121
import android.content.Context;
2222
import android.content.res.ColorStateList;
2323
import android.graphics.drawable.Drawable;
24+
import android.graphics.drawable.GradientDrawable;
25+
import android.graphics.drawable.RippleDrawable;
2426
import android.os.Build;
27+
import android.os.Build.VERSION;
28+
import android.os.Build.VERSION_CODES;
2529
import android.os.Bundle;
2630
import android.os.Parcel;
2731
import android.os.Parcelable;
@@ -35,6 +39,7 @@
3539
import com.google.android.material.behavior.HideBottomViewOnScrollBehavior;
3640
import com.google.android.material.internal.ThemeEnforcement;
3741
import com.google.android.material.resources.MaterialResources;
42+
import com.google.android.material.ripple.RippleUtils;
3843
import com.google.android.material.shape.MaterialShapeDrawable;
3944
import androidx.coordinatorlayout.widget.CoordinatorLayout;
4045
import androidx.core.content.ContextCompat;
@@ -104,6 +109,7 @@ public class BottomNavigationView extends FrameLayout {
104109
private final MenuBuilder menu;
105110
private final BottomNavigationMenuView menuView;
106111
private final BottomNavigationPresenter presenter = new BottomNavigationPresenter();
112+
private ColorStateList itemRippleColor;
107113
private MenuInflater menuInflater;
108114

109115
private OnNavigationItemSelectedListener selectedListener;
@@ -193,7 +199,14 @@ public BottomNavigationView(Context context, AttributeSet attrs, int defStyleAtt
193199
a.getBoolean(R.styleable.BottomNavigationView_itemHorizontalTranslationEnabled, true));
194200

195201
int itemBackground = a.getResourceId(R.styleable.BottomNavigationView_itemBackground, 0);
196-
menuView.setItemBackgroundRes(itemBackground);
202+
if (itemBackground != 0) {
203+
menuView.setItemBackgroundRes(itemBackground);
204+
} else {
205+
ColorStateList itemRippleColor =
206+
MaterialResources.getColorStateList(
207+
context, a, R.styleable.BottomNavigationView_itemRippleColor);
208+
setItemRippleColor(itemRippleColor);
209+
}
197210

198211
if (a.hasValue(R.styleable.BottomNavigationView_menu)) {
199212
inflateMenu(a.getResourceId(R.styleable.BottomNavigationView_menu, 0));
@@ -367,11 +380,14 @@ public int getItemBackgroundResource() {
367380
/**
368381
* Set the background of our menu items to the given resource.
369382
*
383+
* <p>This will remove any ripple backgrounds created by {@link setItemRippleColor()}.
384+
*
370385
* @param resId The identifier of the resource.
371386
* @attr ref R.styleable#BottomNavigationView_itemBackground
372387
*/
373388
public void setItemBackgroundResource(@DrawableRes int resId) {
374389
menuView.setItemBackgroundRes(resId);
390+
itemRippleColor = null;
375391
}
376392

377393
/**
@@ -388,11 +404,63 @@ public Drawable getItemBackground() {
388404
/**
389405
* Set the background of our menu items to the given drawable.
390406
*
407+
* <p>This will remove any ripple backgrounds created by {@link setItemRippleColor()}.
408+
*
391409
* @param background The drawable for the background.
392410
* @attr ref R.styleable#BottomNavigationView_itemBackground
393411
*/
394412
public void setItemBackground(@Nullable Drawable background) {
395413
menuView.setItemBackground(background);
414+
itemRippleColor = null;
415+
}
416+
417+
/**
418+
* Returns the color used to create a ripple as the background drawable of the menu items. If a
419+
* background is set using {@link #setItemBackground()}, this will return null.
420+
*
421+
* @see #setItemBackground(Drawable)
422+
* @attr ref R.styleable#BottomNavigationView_itemRippleColor
423+
*/
424+
public ColorStateList getItemRippleColor() {
425+
return itemRippleColor;
426+
}
427+
428+
/**
429+
* Set the background of our menu items to be a ripple with the given colors.
430+
*
431+
* @param itemRippleColor The {@link ColorStateList} for the ripple. This will create a ripple
432+
* background for menu items, replacing any background previously set by {@link
433+
* #setItemBackground()}.
434+
* @attr ref R.styleable#BottomNavigationView_itemRippleColor
435+
*/
436+
public void setItemRippleColor(ColorStateList itemRippleColor) {
437+
if (this.itemRippleColor == itemRippleColor) {
438+
// Clear the item background when setItemRippleColor(null) is called for consistency.
439+
if (itemRippleColor == null && menuView.getItemBackground() != null) {
440+
menuView.setItemBackground(null);
441+
}
442+
return;
443+
}
444+
445+
this.itemRippleColor = itemRippleColor;
446+
if (itemRippleColor == null) {
447+
menuView.setItemBackground(null);
448+
} else {
449+
ColorStateList rippleDrawableColor =
450+
RippleUtils.convertToRippleDrawableColor(itemRippleColor);
451+
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
452+
menuView.setItemBackground(new RippleDrawable(rippleDrawableColor, null, null));
453+
} else {
454+
GradientDrawable rippleDrawable = new GradientDrawable();
455+
// TODO: Find a workaround for this. Currently on certain devices/versions, LayerDrawable
456+
// will draw a black background underneath any layer with a non-opaque color,
457+
// (e.g. ripple) unless we set the shape to be something that's not a perfect rectangle.
458+
rippleDrawable.setCornerRadius(0.00001F);
459+
Drawable rippleDrawableCompat = DrawableCompat.wrap(rippleDrawable);
460+
DrawableCompat.setTintList(rippleDrawableCompat, rippleDrawableColor);
461+
menuView.setItemBackground(rippleDrawableCompat);
462+
}
463+
}
396464
}
397465

398466
/**
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ Copyright 2019 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+
18+
<selector xmlns:android="http://schemas.android.com/apk/res/android">
19+
20+
<item android:alpha="0.16" android:color="?attr/colorOnPrimary" android:state_pressed="true"/>
21+
<item android:alpha="0.32" android:color="?attr/colorOnPrimary" android:state_focused="true" android:state_hovered="true"/>
22+
<item android:alpha="0.24" android:color="?attr/colorOnPrimary" android:state_focused="true"/>
23+
<item android:alpha="0.08" android:color="?attr/colorOnPrimary" android:state_hovered="true"/>
24+
<item android:alpha="0.00" android:color="?attr/colorOnPrimary"/>
25+
26+
</selector>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ Copyright 2019 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+
18+
<selector xmlns:android="http://schemas.android.com/apk/res/android">
19+
20+
<!-- Selected. -->
21+
22+
<item android:alpha="0.08" android:color="?attr/colorPrimary" android:state_pressed="true" android:state_selected="true"/>
23+
<item android:alpha="0.16" android:color="?attr/colorPrimary" android:state_focused="true" android:state_hovered="true" android:state_selected="true"/>
24+
<item android:alpha="0.12" android:color="?attr/colorPrimary" android:state_focused="true" android:state_selected="true"/>
25+
<item android:alpha="0.04" android:color="?attr/colorPrimary" android:state_hovered="true" android:state_selected="true"/>
26+
<item android:alpha="0.00" android:color="?attr/colorPrimary" android:state_selected="true"/>
27+
28+
<!-- Unselected. -->
29+
30+
<item android:alpha="0.08" android:color="?attr/colorOnSurface" android:state_pressed="true"/>
31+
<item android:alpha="0.16" android:color="?attr/colorOnSurface" android:state_focused="true" android:state_hovered="true"/>
32+
<item android:alpha="0.12" android:color="?attr/colorOnSurface" android:state_focused="true"/>
33+
<item android:alpha="0.04" android:color="?attr/colorOnSurface" android:state_hovered="true"/>
34+
<item android:alpha="0.00" android:color="?attr/colorOnSurface"/>
35+
36+
</selector>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
<!-- The background for the navigation items. Attribute type definition is in navigation
4343
package. -->
4444
<attr name="itemBackground"/>
45+
<!-- The ColorStateList to use for a ripple background. This only exists because creating
46+
ripples in drawable xml based on theme colors is not supported pre-23. This will be ignored
47+
if itemBackground is set.-->
48+
<attr name="itemRippleColor" format="color"/>
4549
<!-- The size to provide for the navigation item icons. -->
4650
<attr name="itemIconSize"/>
4751
<!-- The tint to apply to the navigation item icons. Attribute type definition is in navigation

lib/java/com/google/android/material/bottomnavigation/res/values/styles.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
<item name="android:background">?attr/colorSurface</item>
3434
<item name="enforceTextAppearance">true</item>
3535
<item name="enforceMaterialTheme">true</item>
36+
<item name="itemBackground">@null</item>
3637
<item name="itemHorizontalTranslationEnabled">false</item>
3738
<item name="itemIconTint">@color/mtrl_bottom_nav_item_tint</item>
3839
<item name="itemTextAppearanceInactive">?attr/textAppearanceCaption</item>
3940
<item name="itemTextAppearanceActive">?attr/textAppearanceCaption</item>
4041
<item name="itemTextColor">@color/mtrl_bottom_nav_item_tint</item>
42+
<item name="itemRippleColor">@color/mtrl_bottom_nav_ripple_color</item>
4143
</style>
4244

4345
<!-- Colored style for Bottom NavigationViews.
@@ -48,6 +50,7 @@
4850
<item name="enforceTextAppearance">true</item>
4951
<item name="enforceMaterialTheme">true</item>
5052
<item name="itemIconTint">@color/mtrl_bottom_nav_colored_item_tint</item>
53+
<item name="itemRippleColor">@color/mtrl_bottom_nav_colored_ripple_color</item>
5154
<item name="itemTextAppearanceInactive">?attr/textAppearanceCaption</item>
5255
<item name="itemTextAppearanceActive">?attr/textAppearanceCaption</item>
5356
<item name="itemTextColor">@color/mtrl_bottom_nav_colored_item_tint</item>

0 commit comments

Comments
 (0)