diff options
| author | Chris Banes <chrisbanes@google.com> | 2015-02-23 12:30:13 +0000 |
|---|---|---|
| committer | Chris Banes <chrisbanes@google.com> | 2015-02-27 08:56:04 +0000 |
| commit | 9cc36ca1b520c06f882e84b909f3a2b75d303a06 (patch) | |
| tree | 64778fc1ebedd614503fbea1e81a8dd1cf8f942b /core/java/android | |
| parent | 1b4b87c2aec1ea5487e7279e92114bb1dca013b6 (diff) | |
| download | frameworks_base-9cc36ca1b520c06f882e84b909f3a2b75d303a06.zip frameworks_base-9cc36ca1b520c06f882e84b909f3a2b75d303a06.tar.gz frameworks_base-9cc36ca1b520c06f882e84b909f3a2b75d303a06.tar.bz2 | |
MenuItem, navigation and overflow icon tinting
- iconTint and iconTintMode attrs for MenuItem, with
associated setters.
- navigationTint and navigationTintMode attrs for Toolbar
with associated setters.
- overlflowTint and overflowTintMode attrs for Toolbar
with associated setters.
BUG: 18126050
BUG: 19148351
BUG: 19305408
Change-Id: Ibd1fae7cdbc7a7c42809e52541fae5d8beb18e92
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/view/MenuInflater.java | 32 | ||||
| -rw-r--r-- | core/java/android/view/MenuItem.java | 24 | ||||
| -rw-r--r-- | core/java/android/widget/ActionMenuPresenter.java | 51 | ||||
| -rw-r--r-- | core/java/android/widget/ActionMenuView.java | 27 | ||||
| -rw-r--r-- | core/java/android/widget/Toolbar.java | 150 |
5 files changed, 280 insertions, 4 deletions
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java index 3492aa0..b49a59e 100644 --- a/core/java/android/view/MenuInflater.java +++ b/core/java/android/view/MenuInflater.java @@ -25,8 +25,11 @@ import android.annotation.MenuRes; import android.app.Activity; import android.content.Context; import android.content.ContextWrapper; +import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; import android.util.Xml; @@ -334,6 +337,11 @@ public class MenuInflater { private ActionProvider itemActionProvider; + private ColorStateList itemIconTintList; + private boolean itemIconTintListSet; + private PorterDuff.Mode itemIconTintMode; + private boolean itemIconTintModeSet; + private static final int defaultGroupId = NO_ID; private static final int defaultItemId = NO_ID; private static final int defaultItemCategory = 0; @@ -424,6 +432,23 @@ public class MenuInflater { itemActionProvider = null; } + if (a.hasValueOrEmpty(com.android.internal.R.styleable.MenuItem_iconTint)) { + itemIconTintList = a.getColorStateList( + com.android.internal.R.styleable.MenuItem_iconTint); + itemIconTintListSet = true; + } else { + itemIconTintList = null; + itemIconTintListSet = false; + } + if (a.hasValueOrEmpty(com.android.internal.R.styleable.MenuItem_iconTintMode)) { + itemIconTintMode = Drawable.parseTintMode( + a.getInt(com.android.internal.R.styleable.MenuItem_iconTintMode, -1), null); + itemIconTintModeSet = true; + } else { + itemIconTintMode = null; + itemIconTintModeSet = false; + } + a.recycle(); itemAdded = false; @@ -486,6 +511,13 @@ public class MenuInflater { if (itemActionProvider != null) { item.setActionProvider(itemActionProvider); } + + if (itemIconTintListSet) { + item.setIconTintList(itemIconTintList); + } + if (itemIconTintModeSet) { + item.setIconTintMode(itemIconTintMode); + } } public MenuItem addItem() { diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java index 9e8b97e..2948007 100644 --- a/core/java/android/view/MenuItem.java +++ b/core/java/android/view/MenuItem.java @@ -21,6 +21,8 @@ import android.annotation.LayoutRes; import android.annotation.StringRes; import android.app.Activity; import android.content.Intent; +import android.content.res.ColorStateList; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnCreateContextMenuListener; @@ -599,4 +601,26 @@ public interface MenuItem { * @return This menu item instance for call chaining */ public MenuItem setOnActionExpandListener(OnActionExpandListener listener); + + /** + * Applies a tint to the icon drawable. Does not modify the current tint + * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. + * <p> + * Subsequent calls to {@link android.view.MenuItem#setIcon(android.graphics.drawable.Drawable)} + * will automatically mutate the drawable and apply the specified tint and tint mode. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * @return This menu item instance for call chaining + */ + public MenuItem setIconTintList(ColorStateList tint); + + /** + * Specifies the blending mode used to apply the tint specified by {@link + * #setIconTintList(ColorStateList)} to the icon drawable. The default mode is {@link + * PorterDuff.Mode#SRC_IN}. + * + * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint + * @return This menu item instance for call chaining + */ + public MenuItem setIconTintMode(PorterDuff.Mode tintMode); } diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java index 94827dd..4fadc19 100644 --- a/core/java/android/widget/ActionMenuPresenter.java +++ b/core/java/android/widget/ActionMenuPresenter.java @@ -17,10 +17,10 @@ package android.widget; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; -import android.graphics.Matrix; -import android.graphics.Rect; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; @@ -55,7 +55,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter implements ActionProvider.SubUiVisibilityListener { private static final String TAG = "ActionMenuPresenter"; - private View mOverflowButton; + private OverflowMenuButton mOverflowButton; private boolean mReserveOverflow; private boolean mReserveOverflowSet; private int mWidthLimit; @@ -79,6 +79,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter private OpenOverflowRunnable mPostedOpenRunnable; private ActionMenuPopupCallback mPopupCallback; + private TintInfo mOverflowTintInfo; + final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback(); int mOpenSubMenuId; @@ -113,6 +115,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter mOverflowButton = new OverflowMenuButton(mSystemContext); final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); mOverflowButton.measure(spec, spec); + applyOverflowTint(); } width -= mOverflowButton.getMeasuredWidth(); } else { @@ -236,6 +239,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter if (hasOverflow) { if (mOverflowButton == null) { mOverflowButton = new OverflowMenuButton(mSystemContext); + applyOverflowTint(); } ViewGroup parent = (ViewGroup) mOverflowButton.getParent(); if (parent != mMenuView) { @@ -550,6 +554,40 @@ public class ActionMenuPresenter extends BaseMenuPresenter menuView.initialize(mMenu); } + public void setOverflowTintList(ColorStateList tint) { + if (mOverflowTintInfo == null) { + mOverflowTintInfo = new TintInfo(); + } + mOverflowTintInfo.mTintList = tint; + mOverflowTintInfo.mHasTintList = true; + + applyOverflowTint(); + } + + public void setOverflowTintMode(PorterDuff.Mode tintMode) { + if (mOverflowTintInfo == null) { + mOverflowTintInfo = new TintInfo(); + } + mOverflowTintInfo.mTintMode = tintMode; + mOverflowTintInfo.mHasTintMode = true; + + applyOverflowTint(); + } + + private void applyOverflowTint() { + final TintInfo tintInfo = mOverflowTintInfo; + if (tintInfo != null && (tintInfo.mHasTintList || tintInfo.mHasTintMode)) { + if (mOverflowButton != null) { + if (tintInfo.mHasTintList) { + mOverflowButton.setImageTintList(tintInfo.mTintList); + } + if (tintInfo.mHasTintMode) { + mOverflowButton.setImageTintMode(tintInfo.mTintMode); + } + } + } + } + private static class SavedState implements Parcelable { public int openSubMenuId; @@ -774,4 +812,11 @@ public class ActionMenuPresenter extends BaseMenuPresenter return mActionButtonPopup != null ? mActionButtonPopup.getPopup() : null; } } + + private static class TintInfo { + ColorStateList mTintList; + PorterDuff.Mode mTintMode; + boolean mHasTintMode; + boolean mHasTintList; + } } diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java index 403e4ac..9d3a5dc 100644 --- a/core/java/android/widget/ActionMenuView.java +++ b/core/java/android/widget/ActionMenuView.java @@ -16,7 +16,9 @@ package android.widget; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.Configuration; +import android.graphics.PorterDuff; import android.util.AttributeSet; import android.view.ContextThemeWrapper; import android.view.Gravity; @@ -546,6 +548,31 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo mReserveOverflow = reserveOverflow; } + /** + * Applies a tint to the overflow drawable. Does not modify the current tint + * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. + * + * @param tint the tint to apply, may be {@code null} to clear tint + */ + public void setOverflowTintList(ColorStateList tint) { + if (mPresenter != null) { + mPresenter.setOverflowTintList(tint); + } + } + + /** + * Specifies the blending mode used to apply the tint specified by {@link + * #setOverflowTintList(ColorStateList)} to the overflow drawable. + * The default mode is {@link PorterDuff.Mode#SRC_IN}. + * + * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint + */ + public void setOverflowTintMode(PorterDuff.Mode tintMode) { + if (mPresenter != null) { + mPresenter.setOverflowTintMode(tintMode); + } + } + @Override protected LayoutParams generateDefaultLayoutParams() { LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index c5325c4..9bc2aab 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -20,8 +20,9 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActionBar; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.TypedArray; -import android.graphics.RectF; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; @@ -104,6 +105,9 @@ public class Toolbar extends ViewGroup { private ImageButton mNavButtonView; private ImageView mLogoView; + private TintInfo mOverflowTintInfo; + private TintInfo mNavTintInfo; + private Drawable mCollapseIcon; private CharSequence mCollapseDescription; private ImageButton mCollapseButtonView; @@ -266,6 +270,21 @@ public class Toolbar extends ViewGroup { if (!TextUtils.isEmpty(navDesc)) { setNavigationContentDescription(navDesc); } + + if (a.hasValue(R.styleable.Toolbar_overflowTint)) { + setOverflowTintList(a.getColorStateList(R.styleable.Toolbar_overflowTint)); + } + if (a.hasValue(R.styleable.Toolbar_overflowTintMode)) { + setOverflowTintMode(Drawable.parseTintMode( + a.getInt(R.styleable.Toolbar_overflowTintMode, -1), null)); + } + if (a.hasValue(R.styleable.Toolbar_navigationTint)) { + setNavigationTintList(a.getColorStateList(R.styleable.Toolbar_navigationTint)); + } + if (a.hasValue(R.styleable.Toolbar_navigationTintMode)) { + setNavigationTintMode(Drawable.parseTintMode( + a.getInt(R.styleable.Toolbar_navigationTintMode, -1), null)); + } a.recycle(); } @@ -806,6 +825,91 @@ public class Toolbar extends ViewGroup { } /** + * Applies a tint to the icon drawable. Does not modify the current tint + * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. + * <p> + * Subsequent calls to {@link #setNavigationIcon(Drawable)} will automatically mutate + * the drawable and apply the specified tint and tint mode. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#Toolbar_navigationTint + */ + public void setNavigationTintList(ColorStateList tint) { + if (mNavTintInfo == null) { + mNavTintInfo = new TintInfo(); + } + mNavTintInfo.mTintList = tint; + mNavTintInfo.mHasTintList = true; + + applyNavigationTint(); + } + + /** + * Specifies the blending mode used to apply the tint specified by {@link + * #setNavigationTintList(ColorStateList)} to the navigation drawable. + * The default mode is {@link PorterDuff.Mode#SRC_IN}. + * + * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#Toolbar_navigationTintMode + */ + public void setNavigationTintMode(PorterDuff.Mode tintMode) { + if (mNavTintInfo == null) { + mNavTintInfo = new TintInfo(); + } + mNavTintInfo.mTintMode = tintMode; + mNavTintInfo.mHasTintMode = true; + + applyNavigationTint(); + } + + /** + * Applies a tint to the overflow drawable. Does not modify the current tint + * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#Toolbar_overflowTint + */ + public void setOverflowTintList(ColorStateList tint) { + if (mMenuView != null) { + // If the menu view is available, directly set the tint + mMenuView.setOverflowTintList(tint); + } else { + // Otherwise we will record the value + if (mOverflowTintInfo == null) { + mOverflowTintInfo = new TintInfo(); + } + mOverflowTintInfo.mTintList = tint; + mOverflowTintInfo.mHasTintList = true; + } + } + + /** + * Specifies the blending mode used to apply the tint specified by {@link + * #setOverflowTintList(ColorStateList)} to the overflow drawable. + * The default mode is {@link PorterDuff.Mode#SRC_IN}. + * + * @param tintMode the blending mode used to apply the tint, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#Toolbar_overflowTintMode + */ + public void setOverflowTintMode(PorterDuff.Mode tintMode) { + if (mMenuView != null) { + // If the menu view is available, directly set the tint mode + mMenuView.setOverflowTintMode(tintMode); + } else { + // Otherwise we will record the value + if (mOverflowTintInfo == null) { + mOverflowTintInfo = new TintInfo(); + } + mOverflowTintInfo.mTintMode = tintMode; + mOverflowTintInfo.mHasTintMode = true; + } + } + + /** * Return the Menu shown in the toolbar. * * <p>Applications that wish to populate the toolbar's menu can do so from here. To use @@ -841,6 +945,17 @@ public class Toolbar extends ViewGroup { lp.gravity = Gravity.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK); mMenuView.setLayoutParams(lp); addSystemView(mMenuView); + + if (mOverflowTintInfo != null) { + // If we have tint info for the overflow, set it on the menu view now + if (mOverflowTintInfo.mHasTintList) { + mMenuView.setOverflowTintList(mOverflowTintInfo.mTintList); + } + if (mOverflowTintInfo.mHasTintMode) { + mMenuView.setOverflowTintMode(mOverflowTintInfo.mTintMode); + } + mOverflowTintInfo = null; + } } } @@ -994,6 +1109,7 @@ public class Toolbar extends ViewGroup { final LayoutParams lp = generateDefaultLayoutParams(); lp.gravity = Gravity.START | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK); mNavButtonView.setLayoutParams(lp); + applyNavigationTint(); } } @@ -1012,6 +1128,7 @@ public class Toolbar extends ViewGroup { collapseActionView(); } }); + applyNavigationTint(); } } @@ -1763,6 +1880,30 @@ public class Toolbar extends ViewGroup { return mPopupContext; } + private void applyNavigationTint() { + final TintInfo tintInfo = mNavTintInfo; + if (tintInfo != null && (tintInfo.mHasTintList || tintInfo.mHasTintMode)) { + if (mNavButtonView != null) { + if (tintInfo.mHasTintList) { + mNavButtonView.setImageTintList(tintInfo.mTintList); + } + if (tintInfo.mHasTintMode) { + mNavButtonView.setImageTintMode(tintInfo.mTintMode); + } + } + + if (mCollapseButtonView != null) { + // We will use the same tint for the collapse button + if (tintInfo.mHasTintList) { + mCollapseButtonView.setImageTintList(tintInfo.mTintList); + } + if (tintInfo.mHasTintMode) { + mCollapseButtonView.setImageTintMode(tintInfo.mTintMode); + } + } + } + } + /** * Interface responsible for receiving menu item click events if the items themselves * do not have individual item click listeners. @@ -1990,4 +2131,11 @@ public class Toolbar extends ViewGroup { public void onRestoreInstanceState(Parcelable state) { } } + + private static class TintInfo { + ColorStateList mTintList; + PorterDuff.Mode mTintMode; + boolean mHasTintMode; + boolean mHasTintList; + } } |
