diff options
| author | 2014-06-17 22:12:18 +0000 | |
|---|---|---|
| committer | 2014-06-17 20:42:58 +0000 | |
| commit | 1f681448c6b7db451c31af7d61c0b85b7b5af04f (patch) | |
| tree | 797449e7721c34a3823851cfa0515b4b406f0353 | |
| parent | 6170cca05eb13cfb44c8d13e7a447cd24f27a62c (diff) | |
| parent | 911743652b597057a1bd7ef8a921e9ff8dce0f4a (diff) | |
Merge "Add attributes and accessors for tinting View drawables"
| -rw-r--r-- | api/current.txt | 52 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 106 | ||||
| -rw-r--r-- | core/java/android/widget/AbsSeekBar.java | 108 | ||||
| -rw-r--r-- | core/java/android/widget/CompoundButton.java | 135 | ||||
| -rw-r--r-- | core/java/android/widget/FrameLayout.java | 121 | ||||
| -rw-r--r-- | core/java/android/widget/ImageView.java | 122 | ||||
| -rw-r--r-- | core/java/android/widget/ProgressBar.java | 553 | ||||
| -rw-r--r-- | core/res/res/values/attrs.xml | 188 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 16 | ||||
| -rw-r--r-- | graphics/java/android/graphics/drawable/Drawable.java | 4 |
10 files changed, 1331 insertions, 74 deletions
diff --git a/api/current.txt b/api/current.txt index 8a61cc093675..cf19d542117e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -320,6 +320,8 @@ package android { field public static final int backgroundDimEnabled = 16843295; // 0x101021f field public static final int backgroundSplit = 16843659; // 0x101038b field public static final int backgroundStacked = 16843658; // 0x101038a + field public static final int backgroundTint = 16843885; // 0x101046d + field public static final int backgroundTintMode = 16843886; // 0x101046e field public static final int backupAgent = 16843391; // 0x101027f field public static final int banner = 16843762; // 0x10103f2 field public static final int baseline = 16843548; // 0x101031c @@ -344,6 +346,8 @@ package android { field public static final int buttonStyleInset = 16842826; // 0x101004a field public static final int buttonStyleSmall = 16842825; // 0x1010049 field public static final int buttonStyleToggle = 16842827; // 0x101004b + field public static final int buttonTint = 16843889; // 0x1010471 + field public static final int buttonTintMode = 16843890; // 0x1010472 field public static final int cacheColorHint = 16843009; // 0x1010101 field public static final int calendarViewShown = 16843596; // 0x101034c field public static final int calendarViewStyle = 16843613; // 0x101035d @@ -554,6 +558,8 @@ package android { field public static final int footerDividersEnabled = 16843311; // 0x101022f field public static final int foreground = 16843017; // 0x1010109 field public static final int foregroundGravity = 16843264; // 0x1010200 + field public static final int foregroundTint = 16843887; // 0x101046f + field public static final int foregroundTintMode = 16843888; // 0x1010470 field public static final int format = 16843013; // 0x1010105 field public static final int format12Hour = 16843722; // 0x10103ca field public static final int format24Hour = 16843723; // 0x10103cb @@ -636,6 +642,8 @@ package android { field public static final int indeterminateDuration = 16843069; // 0x101013d field public static final int indeterminateOnly = 16843066; // 0x101013a field public static final int indeterminateProgressStyle = 16843544; // 0x1010318 + field public static final int indeterminateTint = 16843883; // 0x101046b + field public static final int indeterminateTintMode = 16843884; // 0x101046c field public static final int indicatorEnd = 16843730; // 0x10103d2 field public static final int indicatorLeft = 16843021; // 0x101010d field public static final int indicatorRight = 16843022; // 0x101010e @@ -911,6 +919,8 @@ package android { field public static final int privateImeOptions = 16843299; // 0x1010223 field public static final int process = 16842769; // 0x1010011 field public static final int progress = 16843063; // 0x1010137 + field public static final int progressBackgroundTint = 16843879; // 0x1010467 + field public static final int progressBackgroundTintMode = 16843880; // 0x1010468 field public static final int progressBarPadding = 16843545; // 0x1010319 field public static final int progressBarStyle = 16842871; // 0x1010077 field public static final int progressBarStyleHorizontal = 16842872; // 0x1010078 @@ -921,6 +931,8 @@ package android { field public static final int progressBarStyleSmallInverse = 16843400; // 0x1010288 field public static final int progressBarStyleSmallTitle = 16843279; // 0x101020f field public static final int progressDrawable = 16843068; // 0x101013c + field public static final int progressTint = 16843877; // 0x1010465 + field public static final int progressTintMode = 16843878; // 0x1010466 field public static final int prompt = 16843131; // 0x101017b field public static final int propertyName = 16843489; // 0x10102e1 field public static final int protectionLevel = 16842761; // 0x1010009 @@ -1013,6 +1025,8 @@ package android { field public static final int searchSuggestSelection = 16843224; // 0x10101d8 field public static final int searchSuggestThreshold = 16843373; // 0x101026d field public static final int secondaryProgress = 16843064; // 0x1010138 + field public static final int secondaryProgressTint = 16843881; // 0x1010469 + field public static final int secondaryProgressTintMode = 16843882; // 0x101046a field public static final int seekBarStyle = 16842875; // 0x101007b field public static final int segmentedButtonStyle = 16843568; // 0x1010330 field public static final int selectAllOnFocus = 16843102; // 0x101015e @@ -1216,6 +1230,8 @@ package android { field public static final int thumb = 16843074; // 0x1010142 field public static final int thumbOffset = 16843075; // 0x1010143 field public static final int thumbTextPadding = 16843634; // 0x1010372 + field public static final int thumbTint = 16843891; // 0x1010473 + field public static final int thumbTintMode = 16843892; // 0x1010474 field public static final int thumbnail = 16843429; // 0x10102a5 field public static final int tileMode = 16843265; // 0x1010201 field public static final int timeZone = 16843724; // 0x10103cc @@ -32548,6 +32564,8 @@ package android.view { method public android.view.animation.Animation getAnimation(); method public android.os.IBinder getApplicationWindowToken(); method public android.graphics.drawable.Drawable getBackground(); + method public android.content.res.ColorStateList getBackgroundTint(); + method public android.graphics.PorterDuff.Mode getBackgroundTintMode(); method public int getBaseline(); method public final int getBottom(); method protected float getBottomFadingEdgeStrength(); @@ -32825,6 +32843,8 @@ package android.view { method public void setBackgroundColor(int); method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable); method public void setBackgroundResource(int); + method public void setBackgroundTint(android.content.res.ColorStateList); + method public void setBackgroundTintMode(android.graphics.PorterDuff.Mode); method public final void setBottom(int); method public void setCameraDistance(float); method public void setClickable(boolean); @@ -35791,10 +35811,14 @@ package android.widget { method public boolean getSplitTrack(); method public android.graphics.drawable.Drawable getThumb(); method public int getThumbOffset(); + method public android.content.res.ColorStateList getThumbTint(); + method public android.graphics.PorterDuff.Mode getThumbTintMode(); method public void setKeyProgressIncrement(int); method public void setSplitTrack(boolean); method public void setThumb(android.graphics.drawable.Drawable); method public void setThumbOffset(int); + method public void setThumbTint(android.content.res.ColorStateList); + method public void setThumbTintMode(android.graphics.PorterDuff.Mode); } public abstract class AbsSpinner extends android.widget.AdapterView { @@ -36209,9 +36233,13 @@ package android.widget { ctor public CompoundButton(android.content.Context, android.util.AttributeSet); ctor public CompoundButton(android.content.Context, android.util.AttributeSet, int); ctor public CompoundButton(android.content.Context, android.util.AttributeSet, int, int); + method public android.content.res.ColorStateList getButtonTint(); + method public android.graphics.PorterDuff.Mode getButtonTintMode(); method public boolean isChecked(); method public void setButtonDrawable(int); method public void setButtonDrawable(android.graphics.drawable.Drawable); + method public void setButtonTint(android.content.res.ColorStateList); + method public void setButtonTintMode(android.graphics.PorterDuff.Mode); method public void setChecked(boolean); method public void setOnCheckedChangeListener(android.widget.CompoundButton.OnCheckedChangeListener); method public void toggle(); @@ -36472,10 +36500,14 @@ package android.widget { method public deprecated boolean getConsiderGoneChildrenWhenMeasuring(); method public android.graphics.drawable.Drawable getForeground(); method public int getForegroundGravity(); + method public android.content.res.ColorStateList getForegroundTint(); + method public android.graphics.PorterDuff.Mode getForegroundTintMode(); method public boolean getMeasureAllChildren(); method protected void onLayout(boolean, int, int, int, int); method public void setForeground(android.graphics.drawable.Drawable); method public void setForegroundGravity(int); + method public void setForegroundTint(android.content.res.ColorStateList); + method public void setForegroundTintMode(android.graphics.PorterDuff.Mode); method public void setMeasureAllChildren(boolean); } @@ -36684,6 +36716,8 @@ package android.widget { method public int getMaxHeight(); method public int getMaxWidth(); method public android.widget.ImageView.ScaleType getScaleType(); + method public android.content.res.ColorStateList getTint(); + method public android.graphics.PorterDuff.Mode getTintMode(); method public int[] onCreateDrawableState(int); method public void setAdjustViewBounds(boolean); method public deprecated void setAlpha(int); @@ -36705,6 +36739,8 @@ package android.widget { method public void setMaxHeight(int); method public void setMaxWidth(int); method public void setScaleType(android.widget.ImageView.ScaleType); + method public void setTint(android.content.res.ColorStateList); + method public void setTintMode(android.graphics.PorterDuff.Mode); } public static final class ImageView.ScaleType extends java.lang.Enum { @@ -37077,11 +37113,19 @@ package android.widget { ctor public ProgressBar(android.content.Context, android.util.AttributeSet, int); ctor public ProgressBar(android.content.Context, android.util.AttributeSet, int, int); method public android.graphics.drawable.Drawable getIndeterminateDrawable(); + method public android.content.res.ColorStateList getIndeterminateTint(); + method public android.graphics.PorterDuff.Mode getIndeterminateTintMode(); method public android.view.animation.Interpolator getInterpolator(); method public synchronized int getMax(); method public synchronized int getProgress(); + method public android.content.res.ColorStateList getProgressBackgroundTint(); + method public android.graphics.PorterDuff.Mode getProgressBackgroundTintMode(); method public android.graphics.drawable.Drawable getProgressDrawable(); + method public android.content.res.ColorStateList getProgressTint(); + method public android.graphics.PorterDuff.Mode getProgressTintMode(); method public synchronized int getSecondaryProgress(); + method public android.content.res.ColorStateList getSecondaryProgressTint(); + method public android.graphics.PorterDuff.Mode getSecondaryProgressTintMode(); method public final synchronized void incrementProgressBy(int); method public final synchronized void incrementSecondaryProgressBy(int); method public synchronized boolean isIndeterminate(); @@ -37090,13 +37134,21 @@ package android.widget { method public synchronized void setIndeterminate(boolean); method public void setIndeterminateDrawable(android.graphics.drawable.Drawable); method public void setIndeterminateDrawableTiled(android.graphics.drawable.Drawable); + method public void setIndeterminateTint(android.content.res.ColorStateList); + method public void setIndeterminateTintMode(android.graphics.PorterDuff.Mode); method public void setInterpolator(android.content.Context, int); method public void setInterpolator(android.view.animation.Interpolator); method public synchronized void setMax(int); method public synchronized void setProgress(int); + method public void setProgressBackgroundTint(android.content.res.ColorStateList); + method public void setProgressBackgroundTintMode(android.graphics.PorterDuff.Mode); method public void setProgressDrawable(android.graphics.drawable.Drawable); method public void setProgressDrawableTiled(android.graphics.drawable.Drawable); + method public void setProgressTint(android.content.res.ColorStateList); + method public void setProgressTintMode(android.graphics.PorterDuff.Mode); method public synchronized void setSecondaryProgress(int); + method public void setSecondaryProgressTint(android.content.res.ColorStateList); + method public void setSecondaryProgressTintMode(android.graphics.PorterDuff.Mode); } public class QuickContactBadge extends android.widget.ImageView implements android.view.View.OnClickListener { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index d780c880660d..9156216dd619 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -25,6 +25,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ClipData; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; @@ -44,6 +45,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.Shader; +import android.graphics.PorterDuff.Mode; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManagerGlobal; @@ -3187,6 +3189,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_") private Drawable mBackground; + private ColorStateList mBackgroundTint = null; + private PorterDuff.Mode mBackgroundTintMode = PorterDuff.Mode.SRC_ATOP; + private boolean mHasBackgroundTint = false; /** * Display list used for backgrounds. @@ -4022,6 +4027,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setStateListAnimator(AnimatorInflater.loadStateListAnimator(context, a.getResourceId(attr, 0))); break; + case R.styleable.View_backgroundTint: + // This will get applied later during setBackground(). + mBackgroundTint = a.getColorStateList(R.styleable.View_backgroundTint); + mHasBackgroundTint = true; + break; + case R.styleable.View_backgroundTintMode: + // This will get applied later during setBackground(). + mBackgroundTintMode = Drawable.parseTintMode(a.getInt( + R.styleable.View_backgroundTintMode, -1), mBackgroundTintMode); + break; } } @@ -15698,7 +15713,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return; } - Drawable d= null; + Drawable d = null; if (resid != 0) { d = mContext.getDrawable(resid); } @@ -15774,8 +15789,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or // if it has a different minimum size, we should layout again - if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() || - mBackground.getMinimumWidth() != background.getMinimumWidth()) { + if (mBackground == null + || mBackground.getMinimumHeight() != background.getMinimumHeight() + || mBackground.getMinimumWidth() != background.getMinimumWidth()) { requestLayout = true; } @@ -15786,6 +15802,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, background.setVisible(getVisibility() == VISIBLE, false); mBackground = background; + applyBackgroundTint(); + if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { mPrivateFlags &= ~PFLAG_SKIP_DRAW; mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND; @@ -15841,6 +15859,88 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Applies a tint to the background drawable. + * <p> + * Subsequent calls to {@link #setBackground(Drawable)} will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * + * @attr ref android.R.styleable#View_backgroundTint + * @attr ref android.R.styleable#View_backgroundTintMode + * @see Drawable#setTint(ColorStateList, PorterDuff.Mode) + */ + private void setBackgroundTint(@Nullable ColorStateList tint, + @Nullable PorterDuff.Mode tintMode) { + mBackgroundTint = tint; + mBackgroundTintMode = tintMode; + mHasBackgroundTint = true; + + applyBackgroundTint(); + } + + /** + * Applies a tint to the background drawable. Does not modify the current tint + * mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default. + * <p> + * Subsequent calls to {@link #setBackground(Drawable)} will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#View_backgroundTint + * @see #setBackgroundTint(ColorStateList, PorterDuff.Mode) + */ + public void setBackgroundTint(@Nullable ColorStateList tint) { + setBackgroundTint(tint, mBackgroundTintMode); + } + + /** + * @return the tint applied to the background drawable + * @attr ref android.R.styleable#View_backgroundTint + * @see #setBackgroundTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public ColorStateList getBackgroundTint() { + return mBackgroundTint; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setBackgroundTint(ColorStateList)}} to the background drawable. + * The default mode is {@link PorterDuff.Mode#SRC_ATOP}. + * + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#View_backgroundTintMode + * @see #setBackgroundTint(ColorStateList) + */ + public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) { + setBackgroundTint(mBackgroundTint, tintMode); + } + + /** + * @return the blending mode used to apply the tint to the background drawable + * @attr ref android.R.styleable#View_backgroundTintMode + * @see #setBackgroundTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public PorterDuff.Mode getBackgroundTintMode() { + return mBackgroundTintMode; + } + + private void applyBackgroundTint() { + if (mBackground != null && mHasBackgroundTint) { + mBackground = mBackground.mutate(); + mBackground.setTint(mBackgroundTint, mBackgroundTintMode); + } + } + + /** * Sets the padding. The view may add on the space required to display * the scrollbars, depending on the style and visibility of the scrollbars. * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java index 08931fe49196..eb3f88234157 100644 --- a/core/java/android/widget/AbsSeekBar.java +++ b/core/java/android/widget/AbsSeekBar.java @@ -16,11 +16,15 @@ package android.widget; +import android.annotation.Nullable; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Insets; +import android.graphics.PorterDuff; import android.graphics.Rect; +import android.graphics.PorterDuff.Mode; import android.graphics.Region.Op; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -31,10 +35,16 @@ import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; +import com.android.internal.R; + public abstract class AbsSeekBar extends ProgressBar { private final Rect mTempRect = new Rect(); private Drawable mThumb; + private ColorStateList mThumbTint = null; + private PorterDuff.Mode mThumbTintMode = PorterDuff.Mode.SRC_ATOP; + private boolean mHasThumbTint = false; + private int mThumbOffset; private boolean mSplitTrack; @@ -83,6 +93,15 @@ public abstract class AbsSeekBar extends ProgressBar { final Drawable thumb = a.getDrawable(com.android.internal.R.styleable.SeekBar_thumb); setThumb(thumb); + if (a.hasValue(R.styleable.SeekBar_thumbTint)) { + mThumbTint = a.getColorStateList(R.styleable.SeekBar_thumbTint); + mThumbTintMode = Drawable.parseTintMode(a.getInt( + R.styleable.SeekBar_thumbTintMode, -1), mThumbTintMode); + mHasThumbTint = true; + + applyThumbTint(); + } + // Guess thumb offset if thumb != null, but allow layout to override. final int thumbOffset = a.getDimensionPixelOffset( com.android.internal.R.styleable.SeekBar_thumbOffset, getThumbOffset()); @@ -108,7 +127,7 @@ public abstract class AbsSeekBar extends ProgressBar { * @param thumb Drawable representing the thumb */ public void setThumb(Drawable thumb) { - boolean needUpdate; + final boolean needUpdate; // This way, calling setThumb again with the same bitmap will result in // it recalcuating mThumbOffset (if for example it the bounds of the // drawable changed) @@ -118,6 +137,7 @@ public abstract class AbsSeekBar extends ProgressBar { } else { needUpdate = false; } + if (thumb != null) { thumb.setCallback(this); if (canResolveLayoutDirection()) { @@ -136,8 +156,12 @@ public abstract class AbsSeekBar extends ProgressBar { requestLayout(); } } + mThumb = thumb; + + applyThumbTint(); invalidate(); + if (needUpdate) { updateThumbAndTrackPos(getWidth(), getHeight()); if (thumb != null && thumb.isStateful()) { @@ -160,6 +184,88 @@ public abstract class AbsSeekBar extends ProgressBar { } /** + * Applies a tint to the thumb drawable. + * <p> + * Subsequent calls to {@link #setThumb(Drawable)} will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * + * @attr ref android.R.styleable#SeekBar_thumbTint + * @attr ref android.R.styleable#SeekBar_thumbTintMode + * @see Drawable#setTint(ColorStateList, PorterDuff.Mode) + */ + private void setThumbTint(@Nullable ColorStateList tint, + @Nullable PorterDuff.Mode tintMode) { + mThumbTint = tint; + mThumbTintMode = tintMode; + mHasThumbTint = true; + + applyThumbTint(); + } + + /** + * Applies a tint to the thumb drawable. Does not modify the current tint + * mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default. + * <p> + * Subsequent calls to {@link #setThumb(Drawable)} will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#SeekBar_thumbTint + * @see #setThumbTint(ColorStateList, PorterDuff.Mode) + */ + public void setThumbTint(@Nullable ColorStateList tint) { + setThumbTint(tint, mThumbTintMode); + } + + /** + * @return the tint applied to the thumb drawable + * @attr ref android.R.styleable#SeekBar_thumbTint + * @see #setThumbTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public ColorStateList getThumbTint() { + return mThumbTint; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setThumbTint(ColorStateList)}} to the thumb drawable. The + * default mode is {@link PorterDuff.Mode#SRC_ATOP}. + * + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#SeekBar_thumbTintMode + * @see #setThumbTint(ColorStateList) + */ + public void setThumbTintMode(@Nullable PorterDuff.Mode tintMode) { + setThumbTint(mThumbTint, tintMode); + } + + /** + * @return the blending mode used to apply the tint to the thumb drawable + * @attr ref android.R.styleable#SeekBar_thumbTintMode + * @see #setThumbTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public PorterDuff.Mode getThumbTintMode() { + return mThumbTintMode; + } + + private void applyThumbTint() { + if (mThumb != null && mHasThumbTint) { + mThumb = mThumb.mutate(); + mThumb.setTint(mThumbTint, mThumbTintMode); + } + } + + /** * @see #setThumbOffset(int) */ public int getThumbOffset() { diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index c934ad731161..747d2b17bff3 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -16,11 +16,15 @@ package android.widget; +import android.annotation.Nullable; +import android.graphics.PorterDuff; import com.android.internal.R; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Canvas; +import android.graphics.PorterDuff.Mode; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; @@ -48,7 +52,12 @@ public abstract class CompoundButton extends Button implements Checkable { private boolean mChecked; private int mButtonResource; private boolean mBroadcasting; + private Drawable mButtonDrawable; + private ColorStateList mButtonTint = null; + private PorterDuff.Mode mButtonTintMode = PorterDuff.Mode.SRC_ATOP; + private boolean mHasButtonTint = false; + private OnCheckedChangeListener mOnCheckedChangeListener; private OnCheckedChangeListener mOnCheckedChangeWidgetListener; @@ -74,13 +83,22 @@ public abstract class CompoundButton extends Button implements Checkable { final TypedArray a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.CompoundButton, defStyleAttr, defStyleRes); - Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button); + final Drawable d = a.getDrawable(com.android.internal.R.styleable.CompoundButton_button); if (d != null) { setButtonDrawable(d); } - boolean checked = a - .getBoolean(com.android.internal.R.styleable.CompoundButton_checked, false); + if (a.hasValue(R.styleable.CompoundButton_buttonTint)) { + mButtonTint = a.getColorStateList(R.styleable.CompoundButton_buttonTint); + mButtonTintMode = Drawable.parseTintMode(a.getInt( + R.styleable.CompoundButton_buttonTintMode, -1), mButtonTintMode); + mHasButtonTint = true; + + applyButtonTint(); + } + + final boolean checked = a.getBoolean( + com.android.internal.R.styleable.CompoundButton_checked, false); setChecked(checked); a.recycle(); @@ -173,9 +191,11 @@ public abstract class CompoundButton extends Button implements Checkable { } /** - * Set the background to a given Drawable, identified by its resource id. + * Set the button graphic to a given Drawable, identified by its resource + * id. * - * @param resid the resource id of the drawable to use as the background + * @param resid the resource id of the drawable to use as the button + * graphic */ public void setButtonDrawable(int resid) { if (resid != 0 && resid == mButtonResource) { @@ -192,23 +212,114 @@ public abstract class CompoundButton extends Button implements Checkable { } /** - * Set the background to a given Drawable + * Set the button graphic to a given Drawable * - * @param d The Drawable to use as the background + * @param d The Drawable to use as the button graphic */ public void setButtonDrawable(Drawable d) { - if (d != null) { + if (mButtonDrawable != d) { if (mButtonDrawable != null) { mButtonDrawable.setCallback(null); unscheduleDrawable(mButtonDrawable); } - d.setCallback(this); - d.setVisible(getVisibility() == VISIBLE, false); + mButtonDrawable = d; - setMinHeight(mButtonDrawable.getIntrinsicHeight()); + + if (d != null) { + d.setCallback(this); + d.setLayoutDirection(getLayoutDirection()); + if (d.isStateful()) { + d.setState(getDrawableState()); + } + d.setVisible(getVisibility() == VISIBLE, false); + setMinHeight(d.getIntrinsicHeight()); + applyButtonTint(); + } } + } - refreshDrawableState(); + /** + * Applies a tint to the button drawable. + * <p> + * Subsequent calls to {@link #setButtonDrawable(Drawable)} will + * automatically mutate the drawable and apply the specified tint and tint + * mode using + * {@link Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * + * @attr ref android.R.styleable#CompoundButton_buttonTint + * @attr ref android.R.styleable#CompoundButton_buttonTintMode + * @see Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode) + */ + private void setButtonTint(@Nullable ColorStateList tint, + @Nullable PorterDuff.Mode tintMode) { + mButtonTint = tint; + mButtonTintMode = tintMode; + mHasButtonTint = true; + + applyButtonTint(); + } + + /** + * Applies a tint to the button drawable. Does not modify the current tint + * mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default. + * <p> + * Subsequent calls to {@link #setButtonDrawable(Drawable)} will + * automatically mutate the drawable and apply the specified tint and tint + * mode using + * {@link Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#CompoundButton_buttonTint + * @see #setButtonTint(ColorStateList, android.graphics.PorterDuff.Mode) + */ + public void setButtonTint(@Nullable ColorStateList tint) { + setButtonTint(tint, mButtonTintMode); + } + + /** + * @return the tint applied to the button drawable + * @attr ref android.R.styleable#CompoundButton_buttonTint + * @see #setButtonTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public ColorStateList getButtonTint() { + return mButtonTint; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setButtonTint(ColorStateList)}} to the button drawable. The + * default mode is {@link PorterDuff.Mode#SRC_ATOP}. + * + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#CompoundButton_buttonTintMode + * @see #setButtonTint(ColorStateList) + */ + public void setButtonTintMode(@Nullable PorterDuff.Mode tintMode) { + setButtonTint(mButtonTint, tintMode); + } + + /** + * @return the blending mode used to apply the tint to the button drawable + * @attr ref android.R.styleable#CompoundButton_buttonTintMode + * @see #setButtonTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public PorterDuff.Mode getButtonTintMode() { + return mButtonTintMode; + } + + private void applyButtonTint() { + if (mButtonDrawable != null && mHasButtonTint) { + mButtonDrawable = mButtonDrawable.mutate(); + mButtonDrawable.setTint(mButtonTint, mButtonTintMode); + } } @Override diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index 01a6b8aff4b8..5a1492979e08 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -18,11 +18,15 @@ package android.widget; import java.util.ArrayList; +import android.annotation.Nullable; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Canvas; +import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.Region; +import android.graphics.PorterDuff.Mode; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.Gravity; @@ -33,6 +37,8 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.RemoteViews.RemoteView; +import com.android.internal.R; + /** * FrameLayout is designed to block out an area on the screen to display @@ -62,6 +68,9 @@ public class FrameLayout extends ViewGroup { @ViewDebug.ExportedProperty(category = "drawing") private Drawable mForeground; + private ColorStateList mForegroundTint = null; + private PorterDuff.Mode mForegroundTintMode = PorterDuff.Mode.SRC_ATOP; + private boolean mHasForegroundTint = false; @ViewDebug.ExportedProperty(category = "padding") private int mForegroundPaddingLeft = 0; @@ -119,6 +128,15 @@ public class FrameLayout extends ViewGroup { setMeasureAllChildren(true); } + if (a.hasValue(R.styleable.FrameLayout_foregroundTint)) { + mForegroundTint = a.getColorStateList(R.styleable.FrameLayout_foregroundTint); + mForegroundTintMode = Drawable.parseTintMode(a.getInt( + R.styleable.FrameLayout_foregroundTintMode, -1), mForegroundTintMode); + mHasForegroundTint = true; + + applyForegroundTint(); + } + mForegroundInPadding = a.getBoolean( com.android.internal.R.styleable.FrameLayout_foregroundInsidePadding, true); @@ -231,32 +249,34 @@ public class FrameLayout extends ViewGroup { * into account by ensuring that the children are inset to be placed * inside of the padding area. * - * @param drawable The Drawable to be drawn on top of the children. + * @param d The Drawable to be drawn on top of the children. * * @attr ref android.R.styleable#FrameLayout_foreground */ - public void setForeground(Drawable drawable) { - if (mForeground != drawable) { + public void setForeground(Drawable d) { + if (mForeground != d) { if (mForeground != null) { mForeground.setCallback(null); unscheduleDrawable(mForeground); } - mForeground = drawable; + mForeground = d; mForegroundPaddingLeft = 0; mForegroundPaddingTop = 0; mForegroundPaddingRight = 0; mForegroundPaddingBottom = 0; - if (drawable != null) { + if (d != null) { setWillNotDraw(false); - drawable.setCallback(this); - if (drawable.isStateful()) { - drawable.setState(getDrawableState()); + d.setCallback(this); + d.setLayoutDirection(getLayoutDirection()); + if (d.isStateful()) { + d.setState(getDrawableState()); } + applyForegroundTint(); if (mForegroundGravity == Gravity.FILL) { Rect padding = new Rect(); - if (drawable.getPadding(padding)) { + if (d.getPadding(padding)) { mForegroundPaddingLeft = padding.left; mForegroundPaddingTop = padding.top; mForegroundPaddingRight = padding.right; @@ -281,6 +301,89 @@ public class FrameLayout extends ViewGroup { return mForeground; } + /** + * Applies a tint to the foreground drawable. + * <p> + * Subsequent calls to {@link #setForeground(Drawable)} will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * + * @attr ref android.R.styleable#FrameLayout_foregroundTint + * @attr ref android.R.styleable#FrameLayout_foregroundTintMode + * @see Drawable#setTint(ColorStateList, PorterDuff.Mode) + */ + private void setForegroundTint(@Nullable ColorStateList tint, + @Nullable PorterDuff.Mode tintMode) { + mForegroundTint = tint; + mForegroundTintMode = tintMode; + mHasForegroundTint = true; + + applyForegroundTint(); + } + + /** + * Applies a tint to the foreground drawable. Does not modify the current + * tint mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default. + * <p> + * Subsequent calls to {@link #setForeground(Drawable)} will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#FrameLayout_foregroundTint + * @see #setForegroundTint(ColorStateList, PorterDuff.Mode) + */ + public void setForegroundTint(@Nullable ColorStateList tint) { + setForegroundTint(tint, mForegroundTintMode); + } + + /** + * @return the tint applied to the foreground drawable + * @attr ref android.R.styleable#FrameLayout_foregroundTint + * @see #setForegroundTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public ColorStateList getForegroundTint() { + return mForegroundTint; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setForegroundTint(ColorStateList)}} to the foreground drawable. + * The default mode is {@link PorterDuff.Mode#SRC_ATOP}. + * + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#FrameLayout_foregroundTintMode + * @see #setForegroundTint(ColorStateList) + */ + public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) { + setForegroundTint(mForegroundTint, tintMode); + } + + /** + * @return the blending mode used to apply the tint to the foreground + * drawable + * @attr ref android.R.styleable#FrameLayout_foregroundTintMode + * @see #setForegroundTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public PorterDuff.Mode getForegroundTintMode() { + return mForegroundTintMode; + } + + private void applyForegroundTint() { + if (mForeground != null && mHasForegroundTint) { + mForeground = mForeground.mutate(); + mForeground.setTint(mForegroundTint, mForegroundTintMode); + } + } + int getPaddingLeftWithForeground() { return mForegroundInPadding ? Math.max(mPaddingLeft, mForegroundPaddingLeft) : mPaddingLeft + mForegroundPaddingLeft; diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index a40b85eccef0..399e08719c12 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -16,8 +16,10 @@ package android.widget; +import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; @@ -30,6 +32,7 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Xfermode; +import android.graphics.PorterDuff.Mode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -44,6 +47,8 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.RemoteViews.RemoteView; +import com.android.internal.R; + import java.io.IOException; import java.io.InputStream; @@ -75,13 +80,18 @@ public class ImageView extends View { private int mMaxHeight = Integer.MAX_VALUE; // these are applied to the drawable - private ColorFilter mColorFilter; + private ColorFilter mColorFilter = null; + private boolean mHasColorFilter = false; private Xfermode mXfermode; private int mAlpha = 255; private int mViewAlphaScale = 256; private boolean mColorMod = false; private Drawable mDrawable = null; + private ColorStateList mDrawableTint = null; + private PorterDuff.Mode mDrawableTintMode = PorterDuff.Mode.SRC_ATOP; + private boolean mHasDrawableTint = false; + private int[] mState = null; private boolean mMergeState = false; private int mLevel = 0; @@ -154,17 +164,21 @@ public class ImageView extends View { setMaxHeight(a.getDimensionPixelSize( com.android.internal.R.styleable.ImageView_maxHeight, Integer.MAX_VALUE)); - int index = a.getInt(com.android.internal.R.styleable.ImageView_scaleType, -1); + final int index = a.getInt(com.android.internal.R.styleable.ImageView_scaleType, -1); if (index >= 0) { setScaleType(sScaleTypeArray[index]); } - int tint = a.getInt(com.android.internal.R.styleable.ImageView_tint, 0); - if (tint != 0) { - setColorFilter(tint); + if (a.hasValue(R.styleable.ImageView_tint)) { + mDrawableTint = a.getColorStateList(R.styleable.ImageView_tint); + mDrawableTintMode = Drawable.parseTintMode(a.getInt( + R.styleable.ImageView_tintMode, -1), mDrawableTintMode); + mHasDrawableTint = true; + + applyDrawableTint(); } - - int alpha = a.getInt(com.android.internal.R.styleable.ImageView_drawableAlpha, 255); + + final int alpha = a.getInt(com.android.internal.R.styleable.ImageView_drawableAlpha, 255); if (alpha != 255) { setAlpha(alpha); } @@ -435,6 +449,88 @@ public class ImageView extends View { } /** + * Applies a tint to the image drawable. + * <p> + * Subsequent calls to {@link #setImageDrawable(Drawable)} will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * + * @attr ref android.R.styleable#ImageView_tint + * @attr ref android.R.styleable#ImageView_tintMode + * @see Drawable#setTint(ColorStateList, PorterDuff.Mode) + */ + private void setTint(@Nullable ColorStateList tint, + @Nullable PorterDuff.Mode tintMode) { + mDrawableTint = tint; + mDrawableTintMode = tintMode; + mHasDrawableTint = true; + + applyDrawableTint(); + } + + /** + * Applies a tint to the image drawable. Does not modify the current tint + * mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default. + * <p> + * Subsequent calls to {@link #setImageDrawable(Drawable)} will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#ImageView_tint + * @see Drawable#setTint(ColorStateList, PorterDuff.Mode) + */ + public void setTint(@Nullable ColorStateList tint) { + setTint(tint, mDrawableTintMode); + } + + /** + * @return the tint applied to the image drawable + * @attr ref android.R.styleable#ImageView_tint + * @see #setTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public ColorStateList getTint() { + return mDrawableTint; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setTint(ColorStateList)}} to the image drawable. The default + * mode is {@link PorterDuff.Mode#SRC_ATOP}. + * + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#ImageView_tintMode + * @see #setTint(ColorStateList) + */ + public void setTintMode(@Nullable PorterDuff.Mode tintMode) { + setTint(mDrawableTint, tintMode); + } + + /** + * @return the blending mode used to apply the tint to the image drawable + * @attr ref android.R.styleable#ImageView_tintMode + * @see #setTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public PorterDuff.Mode getTintMode() { + return mDrawableTintMode; + } + + private void applyDrawableTint() { + if (mDrawable != null && mHasDrawableTint) { + mDrawable = mDrawable.mutate(); + mDrawable.setTint(mDrawableTint, mDrawableTintMode); + } + } + + /** * Sets a Bitmap as the content of this ImageView. * * @param bm The bitmap to set @@ -709,17 +805,20 @@ public class ImageView extends View { mDrawable.setCallback(null); unscheduleDrawable(mDrawable); } + mDrawable = d; + if (d != null) { d.setCallback(this); + d.setLayoutDirection(getLayoutDirection()); if (d.isStateful()) { d.setState(getDrawableState()); } - d.setLevel(mLevel); - d.setLayoutDirection(getLayoutDirection()); d.setVisible(getVisibility() == VISIBLE, true); + d.setLevel(mLevel); mDrawableWidth = d.getIntrinsicWidth(); mDrawableHeight = d.getIntrinsicHeight(); + applyDrawableTint(); applyColorMod(); configureBounds(); } else { @@ -1177,6 +1276,7 @@ public class ImageView extends View { public void setColorFilter(ColorFilter cf) { if (mColorFilter != cf) { mColorFilter = cf; + mHasColorFilter = true; mColorMod = true; applyColorMod(); invalidate(); @@ -1231,7 +1331,9 @@ public class ImageView extends View { // re-applied if the Drawable is changed. if (mDrawable != null && mColorMod) { mDrawable = mDrawable.mutate(); - mDrawable.setColorFilter(mColorFilter); + if (mHasColorFilter) { + mDrawable.setColorFilter(mColorFilter); + } mDrawable.setXfermode(mXfermode); mDrawable.setAlpha(mAlpha * mViewAlphaScale >> 8); } diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index af32f1ca2013..62a8becf6372 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -16,13 +16,17 @@ package android.widget; +import android.annotation.Nullable; +import android.graphics.PorterDuff; import com.android.internal.R; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; +import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.graphics.Shader; import android.graphics.drawable.Animatable; @@ -210,8 +214,26 @@ public class ProgressBar extends View { private Transformation mTransformation; private AlphaAnimation mAnimation; private boolean mHasAnimation; + private Drawable mIndeterminateDrawable; + private ColorStateList mIndeterminateTint = null; + private PorterDuff.Mode mIndeterminateTintMode = PorterDuff.Mode.SRC_ATOP; + private boolean mHasIndeterminateTint = false; + private Drawable mProgressDrawable; + + private ColorStateList mProgressTint = null; + private PorterDuff.Mode mProgressTintMode = PorterDuff.Mode.SRC_ATOP; + private boolean mHasProgressTint = false; + + private ColorStateList mProgressBackgroundTint = null; + private PorterDuff.Mode mProgressBackgroundTintMode = PorterDuff.Mode.SRC_ATOP; + private boolean mHasProgressBackgroundTint = false; + + private ColorStateList mSecondaryProgressTint = null; + private PorterDuff.Mode mSecondaryProgressTintMode = PorterDuff.Mode.SRC_ATOP; + private boolean mHasSecondaryProgressTint = false; + private Drawable mCurrentDrawable; Bitmap mSampleTile; private boolean mNoInvalidate; @@ -257,11 +279,11 @@ public class ProgressBar extends View { mNoInvalidate = true; - Drawable drawable = a.getDrawable(R.styleable.ProgressBar_progressDrawable); - if (drawable != null) { + final Drawable progressDrawable = a.getDrawable(R.styleable.ProgressBar_progressDrawable); + if (progressDrawable != null) { // Calling this method can set mMaxHeight, make sure the corresponding // XML attribute for mMaxHeight is read after calling this method - setProgressDrawableTiled(drawable); + setProgressDrawableTiled(progressDrawable); } @@ -288,9 +310,10 @@ public class ProgressBar extends View { setSecondaryProgress( a.getInt(R.styleable.ProgressBar_secondaryProgress, mSecondaryProgress)); - drawable = a.getDrawable(R.styleable.ProgressBar_indeterminateDrawable); - if (drawable != null) { - setIndeterminateDrawableTiled(drawable); + final Drawable indeterminateDrawable = a.getDrawable( + R.styleable.ProgressBar_indeterminateDrawable); + if (indeterminateDrawable != null) { + setIndeterminateDrawableTiled(indeterminateDrawable); } mOnlyIndeterminate = a.getBoolean( @@ -303,6 +326,53 @@ public class ProgressBar extends View { mMirrorForRtl = a.getBoolean(R.styleable.ProgressBar_mirrorForRtl, mMirrorForRtl); + if (a.hasValue(R.styleable.ProgressBar_progressTint)) { + mProgressTint = a.getColorStateList( + R.styleable.ProgressBar_progressTint); + mProgressTintMode = Drawable.parseTintMode(a.getInt( + R.styleable.ProgressBar_progressBackgroundTintMode, -1), + mProgressTintMode); + mHasProgressTint = true; + + applyProgressLayerTint(R.id.progress, mProgressTint, + mProgressTintMode, true); + } + + if (a.hasValue(R.styleable.ProgressBar_progressBackgroundTint)) { + mProgressBackgroundTint = a.getColorStateList( + R.styleable.ProgressBar_progressBackgroundTint); + mProgressBackgroundTintMode = Drawable.parseTintMode(a.getInt( + R.styleable.ProgressBar_progressTintMode, -1), + mProgressBackgroundTintMode); + mHasProgressBackgroundTint = true; + + applyProgressLayerTint(R.id.background, mProgressBackgroundTint, + mProgressBackgroundTintMode, false); + } + + if (a.hasValue(R.styleable.ProgressBar_secondaryProgressTint)) { + mSecondaryProgressTint = a.getColorStateList( + R.styleable.ProgressBar_secondaryProgressTint); + mSecondaryProgressTintMode = Drawable.parseTintMode(a.getInt( + R.styleable.ProgressBar_secondaryProgressTintMode, -1), + mSecondaryProgressTintMode); + mHasSecondaryProgressTint = true; + + applyProgressLayerTint(R.id.secondaryProgress, mSecondaryProgressTint, + mSecondaryProgressTintMode, false); + } + + if (a.hasValue(R.styleable.ProgressBar_indeterminateTint)) { + mIndeterminateTint = a.getColorStateList( + R.styleable.ProgressBar_indeterminateTint); + mIndeterminateTintMode = Drawable.parseTintMode(a.getInt( + R.styleable.ProgressBar_indeterminateTintMode, -1), + mIndeterminateTintMode); + mHasIndeterminateTint = true; + + applyIndeterminateTint(); + } + a.recycle(); // If not explicitly specified this view is important for accessibility. @@ -479,16 +549,111 @@ public class ProgressBar extends View { * @see #setIndeterminate(boolean) */ public void setIndeterminateDrawable(Drawable d) { - if (d != null) { - d.setCallback(this); - } - mIndeterminateDrawable = d; - if (mIndeterminateDrawable != null && canResolveLayoutDirection()) { - mIndeterminateDrawable.setLayoutDirection(getLayoutDirection()); + if (mIndeterminateDrawable != d) { + if (mIndeterminateDrawable != null) { + mIndeterminateDrawable.setCallback(null); + unscheduleDrawable(mIndeterminateDrawable); + } + + mIndeterminateDrawable = d; + + if (d != null) { + d.setCallback(this); + d.setLayoutDirection(getLayoutDirection()); + if (d.isStateful()) { + d.setState(getDrawableState()); + } + applyIndeterminateTint(); + } + + if (mIndeterminate) { + mCurrentDrawable = d; + postInvalidate(); + } } - if (mIndeterminate) { - mCurrentDrawable = d; - postInvalidate(); + } + + /** + * Applies a tint to the indeterminate drawable. + * <p> + * Subsequent calls to {@link #setVisibilminateDrawable(Drawable)} will + * automatically mutate the drawable and apply the specified tint and + * tint mode using + * {@link Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * + * @attr ref android.R.styleable#ProgressBar_indeterminateTint + * @attr ref android.R.styleable#ProgressBar_indeterminateTintMode + * @see Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode) + */ + private void setIndeterminateTint(@Nullable ColorStateList tint, + @Nullable PorterDuff.Mode tintMode) { + mIndeterminateTint = tint; + mIndeterminateTintMode = tintMode; + mHasIndeterminateTint = true; + + applyIndeterminateTint(); + } + + /** + * Applies a tint to the indeterminate drawable. Does not modify the + * current tint mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default. + * <p> + * Subsequent calls to {@link #setIndeterminateDrawable(Drawable)} will + * automatically mutate the drawable and apply the specified tint and + * tint mode using + * {@link Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#ProgressBar_indeterminateTint + * @see #setIndeterminateTint(ColorStateList, PorterDuff.Mode) + */ + public void setIndeterminateTint(@Nullable ColorStateList tint) { + setIndeterminateTint(tint, mIndeterminateTintMode); + } + + /** + * @return the tint applied to the indeterminate drawable + * @attr ref android.R.styleable#ProgressBar_indeterminateTint + * @see #setIndeterminateTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public ColorStateList getIndeterminateTint() { + return mIndeterminateTint; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setIndeterminateTint(ColorStateList)} to the indeterminate + * drawable. The default mode is {@link PorterDuff.Mode#SRC_ATOP}. + * + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#ProgressBar_indeterminateTintMode + * @see #setIndeterminateTint(ColorStateList) + */ + public void setIndeterminateTintMode(@Nullable PorterDuff.Mode tintMode) { + setIndeterminateTint(mIndeterminateTint, tintMode); + } + + /** + * @return the blending mode used to apply the tint to the indeterminate drawable + * @attr ref android.R.styleable#ProgressBar_indeterminateTintMode + * @see #setIndeterminateTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public PorterDuff.Mode getIndeterminateTintMode() { + return mIndeterminateTintMode; + } + + private void applyIndeterminateTint() { + if (mIndeterminateDrawable != null && mHasIndeterminateTint) { + mIndeterminateDrawable = mIndeterminateDrawable.mutate(); + mIndeterminateDrawable.setTint(mIndeterminateTint, mIndeterminateTintMode); } } @@ -532,42 +697,340 @@ public class ProgressBar extends View { * @see #setIndeterminate(boolean) */ public void setProgressDrawable(Drawable d) { - boolean needUpdate; - if (mProgressDrawable != null && d != mProgressDrawable) { - mProgressDrawable.setCallback(null); - needUpdate = true; - } else { - needUpdate = false; - } + if (mProgressDrawable != d) { + if (mProgressDrawable != null) { + mProgressDrawable.setCallback(null); + unscheduleDrawable(mProgressDrawable); + } - if (d != null) { - d.setCallback(this); - if (canResolveLayoutDirection()) { + mProgressDrawable = d; + + if (d != null) { + d.setCallback(this); d.setLayoutDirection(getLayoutDirection()); + if (d.isStateful()) { + d.setState(getDrawableState()); + } + + // Make sure the ProgressBar is always tall enough + int drawableHeight = d.getMinimumHeight(); + if (mMaxHeight < drawableHeight) { + mMaxHeight = drawableHeight; + requestLayout(); + } + + if (mHasProgressTint) { + applyProgressLayerTint(R.id.progress, mProgressTint, mProgressTintMode, true); + } + + if (mHasProgressBackgroundTint) { + applyProgressLayerTint(R.id.background, mProgressBackgroundTint, + mProgressBackgroundTintMode, false); + } + + if (mHasSecondaryProgressTint) { + applyProgressLayerTint(R.id.secondaryProgress, mSecondaryProgressTint, + mSecondaryProgressTintMode, false); + } } - // Make sure the ProgressBar is always tall enough - int drawableHeight = d.getMinimumHeight(); - if (mMaxHeight < drawableHeight) { - mMaxHeight = drawableHeight; - requestLayout(); + if (!mIndeterminate) { + mCurrentDrawable = d; + postInvalidate(); } - } - mProgressDrawable = d; - if (!mIndeterminate) { - mCurrentDrawable = d; - postInvalidate(); - } - if (needUpdate) { updateDrawableBounds(getWidth(), getHeight()); updateDrawableState(); + doRefreshProgress(R.id.progress, mProgress, false, false); doRefreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false); } } /** + * Applies a tint to the progress indicator, if one exists, or to the + * entire progress drawable otherwise. + * <p> + * The progress indicator should be specified as a layer with + * id {@link android.R.id#progress} in a {@link LayerDrawable} + * used as the progress drawable. + * <p> + * Subsequent calls to {@link #setProgressDrawable(Drawable)} will + * automatically mutate the drawable and apply the specified tint and + * tint mode using + * {@link Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * + * @attr ref android.R.styleable#ProgressBar_progressTint + * @attr ref android.R.styleable#ProgressBar_progressTintMode + * @see Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode) + */ + private void setProgressTint(@Nullable ColorStateList tint, + @Nullable PorterDuff.Mode tintMode) { + mProgressTint = tint; + mProgressTintMode = tintMode; + mHasProgressTint = true; + + applyProgressLayerTint(R.id.progress, tint, tintMode, true); + } + + /** + * Applies a tint to the progress indicator, if one exists, or to the + * entire progress drawable otherwise. Does not modify the current tint + * mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default. + * <p> + * The progress indicator should be specified as a layer with + * id {@link android.R.id#progress} in a {@link LayerDrawable} + * used as the progress drawable. + * <p> + * Subsequent calls to {@link #setProgressDrawable(Drawable)} will + * automatically mutate the drawable and apply the specified tint and + * tint mode using + * {@link Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#ProgressBar_progressTint + * @see #setProgressTint(ColorStateList) + */ + public void setProgressTint(@Nullable ColorStateList tint) { + setProgressTint(tint, mProgressTintMode); + } + + /** + * @return the tint applied to the progress drawable + * @attr ref android.R.styleable#ProgressBar_progressTint + * @see #setProgressTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public ColorStateList getProgressTint() { + return mProgressTint; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setProgressTint(ColorStateList)}} to the progress + * indicator. The default mode is {@link PorterDuff.Mode#SRC_ATOP}. + * + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#ProgressBar_progressTintMode + * @see #setProgressTint(ColorStateList) + */ + public void setProgressTintMode(@Nullable PorterDuff.Mode tintMode) { + setProgressTint(mProgressTint, tintMode); + } + + /** + * @return the blending mode used to apply the tint to the progress drawable + * @attr ref android.R.styleable#ProgressBar_progressTintMode + * @see #setProgressTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public PorterDuff.Mode getProgressTintMode() { + return mProgressTintMode; + } + + /** + * Applies a tint to the progress background, if one exists. + * <p> + * The progress background must be specified as a layer with + * id {@link android.R.id#background} in a {@link LayerDrawable} + * used as the progress drawable. + * <p> + * Subsequent calls to {@link #setProgressDrawable(Drawable)} where the + * drawable contains a progress background will automatically mutate the + * drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * + * @attr ref android.R.styleable#ProgressBar_progressBackgroundTint + * @attr ref android.R.styleable#ProgressBar_progressBackgroundTintMode + * @see Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode) + */ + private void setProgressBackgroundTint(@Nullable ColorStateList tint, + @Nullable PorterDuff.Mode tintMode) { + mProgressBackgroundTint = tint; + mProgressBackgroundTintMode = tintMode; + mHasProgressBackgroundTint = true; + + applyProgressLayerTint(R.id.background, tint, tintMode, false); + } + + /** + * Applies a tint to the progress background, if one exists. Does not + * modify the current tint mode, which is + * {@link PorterDuff.Mode#SRC_ATOP} by default. + * <p> + * The progress background must be specified as a layer with + * id {@link android.R.id#background} in a {@link LayerDrawable} + * used as the progress drawable. + * <p> + * Subsequent calls to {@link #setProgressDrawable(Drawable)} where the + * drawable contains a progress background will automatically mutate the + * drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#ProgressBar_progressBackgroundTint + * @see #setProgressBackgroundTint(ColorStateList, PorterDuff.Mode) + */ + public void setProgressBackgroundTint(@Nullable ColorStateList tint) { + setProgressBackgroundTint(tint, mProgressBackgroundTintMode); + } + + /** + * @return the tint applied to the progress background + * @attr ref android.R.styleable#ProgressBar_progressBackgroundTint + * @see #setProgressBackgroundTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public ColorStateList getProgressBackgroundTint() { + return mProgressBackgroundTint; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setProgressBackgroundTint(ColorStateList)}} to the progress + * background. The default mode is {@link PorterDuff.Mode#SRC_ATOP}. + * + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#ProgressBar_progressBackgroundTintMode + * @see #setProgressBackgroundTint(ColorStateList) + */ + public void setProgressBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) { + setProgressBackgroundTint(mProgressBackgroundTint, tintMode); + } + + /** + * @return the blending mode used to apply the tint to the progress + * background + * @attr ref android.R.styleable#ProgressBar_progressBackgroundTintMode + * @see #setProgressBackgroundTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public PorterDuff.Mode getProgressBackgroundTintMode() { + return mProgressBackgroundTintMode; + } + + /** + * Applies a tint to the secondary progress indicator, if one exists. + * <p> + * The secondary progress indicator must be specified as a layer with + * id {@link android.R.id#secondaryProgress} in a {@link LayerDrawable} + * used as the progress drawable. + * <p> + * Subsequent calls to {@link #setProgressDrawable(Drawable)} where the + * drawable contains a secondary progress indicator will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * + * @attr ref android.R.styleable#ProgressBar_secondaryProgressTint + * @attr ref android.R.styleable#ProgressBar_secondaryProgressTintMode + * @see Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode) + */ + private void setSecondaryProgressTint(@Nullable ColorStateList tint, + @Nullable PorterDuff.Mode tintMode) { + mSecondaryProgressTint = tint; + mSecondaryProgressTintMode = tintMode; + mHasSecondaryProgressTint = true; + + applyProgressLayerTint(R.id.secondaryProgress, tint, tintMode, false); + } + + /** + * Applies a tint to the secondary progress indicator, if one exists. + * Does not modify the current tint mode, which is + * {@link PorterDuff.Mode#SRC_ATOP} by default. + * <p> + * The secondary progress indicator must be specified as a layer with + * id {@link android.R.id#secondaryProgress} in a {@link LayerDrawable} + * used as the progress drawable. + * <p> + * Subsequent calls to {@link #setProgressDrawable(Drawable)} where the + * drawable contains a secondary progress indicator will automatically + * mutate the drawable and apply the specified tint and tint mode using + * {@link Drawable#setTint(ColorStateList, android.graphics.PorterDuff.Mode)}. + * + * @param tint the tint to apply, may be {@code null} to clear tint + * + * @attr ref android.R.styleable#ProgressBar_secondaryProgressTint + * @see #setSecondaryProgressTint(ColorStateList, PorterDuff.Mode) + */ + public void setSecondaryProgressTint(@Nullable ColorStateList tint) { + setSecondaryProgressTint(tint, mSecondaryProgressTintMode); + } + + /** + * @return the tint applied to the secondary progress drawable + * @attr ref android.R.styleable#ProgressBar_secondaryProgressTint + * @see #setSecondaryProgressTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public ColorStateList getSecondaryProgressTint() { + return mSecondaryProgressTint; + } + + /** + * Specifies the blending mode used to apply the tint specified by + * {@link #setSecondaryProgressTint(ColorStateList)}} to the secondary + * progress indicator. The default mode is + * {@link PorterDuff.Mode#SRC_ATOP}. + * + * @param tintMode the blending mode used to apply the tint, may be + * {@code null} to clear tint + * @attr ref android.R.styleable#ProgressBar_secondaryProgressTintMode + * @see #setSecondaryProgressTint(ColorStateList) + */ + public void setSecondaryProgressTintMode(@Nullable PorterDuff.Mode tintMode) { + setSecondaryProgressTint(mSecondaryProgressTint, tintMode); + } + + /** + * @return the blending mode used to apply the tint to the secondary + * progress drawable + * @attr ref android.R.styleable#ProgressBar_secondaryProgressTintMode + * @see #setSecondaryProgressTint(ColorStateList, PorterDuff.Mode) + */ + @Nullable + public PorterDuff.Mode getSecondaryProgressTintMode() { + return mSecondaryProgressTintMode; + } + + private void applyProgressLayerTint(int layerId, @Nullable ColorStateList tint, + @Nullable PorterDuff.Mode tintMode, boolean shouldFallback) { + final Drawable d = mProgressDrawable; + if (d != null) { + mProgressDrawable = d.mutate(); + + Drawable layer = null; + if (d instanceof LayerDrawable) { + layer = ((LayerDrawable) d).findDrawableByLayerId(layerId); + } + + if (shouldFallback && layer == null) { + layer = d; + } + + if (layer != null) { + layer.setTint(tint, tintMode); + } + } + } + + /** * Define the tileable drawable used to draw the progress bar in * progress mode. * <p> @@ -670,6 +1133,22 @@ public class ProgressBar extends View { } } + private void setDrawableTint(int id, ColorStateList tint, Mode tintMode, boolean fallback) { + Drawable layer = null; + + // We expect a layer drawable, so try to find the target ID. + final Drawable d = mCurrentDrawable; + if (d instanceof LayerDrawable) { + layer = ((LayerDrawable) d).findDrawableByLayerId(id); + } + + if (fallback && layer == null) { + layer = d; + } + + layer.mutate().setTint(tint, tintMode); + } + private synchronized void doRefreshProgress(int id, int progress, boolean fromUser, boolean callBackToApp) { float scale = mMax > 0 ? (float) progress / (float) mMax : 0; diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index e807d6928969..8d8f69e87df8 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2432,6 +2432,30 @@ <!-- Sets the state-based animator for the View. --> <attr name="stateListAnimator" format="reference"/> + + <!-- Tint to apply to the background. --> + <attr name="backgroundTint" format="color" /> + + <!-- Blending mode used to apply the background tint. --> + <attr name="backgroundTintMode"> + <!-- The tint is drawn on top of the drawable. + [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] --> + <enum name="src_over" value="3" /> + <!-- The tint is masked by the alpha channel of the drawable. The drawable’s + color channels are thrown out. [Sa * Da, Sc * Da] --> + <enum name="src_in" value="5" /> + <!-- The tint is drawn above the drawable, but with the drawable’s alpha + channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] --> + <enum name="src_atop" value="9" /> + <!-- Multiplies the color and alpha channels of the drawable with those of + the tint. [Sa * Da, Sc * Dc] --> + <enum name="multiply" value="14" /> + <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] --> + <enum name="screen" value="15" /> + <!-- Combines the tint and drawable color and alpha channels, clamping the + result to valid color values. Saturate(S + D) --> + <enum name="add" value="16" /> + </attr> </declare-styleable> <!-- Attributes that can be assigned to a tag for a particular View. --> @@ -3021,7 +3045,29 @@ <!-- Indicates the initial checked state of this button. --> <attr name="checked" format="boolean" /> <!-- Drawable used for the button graphic (e.g. checkbox, radio button, etc). --> - <attr name="button" format="reference"/> + <attr name="button" format="reference" /> + <!-- Tint to apply to the button graphic. --> + <attr name="buttonTint" format="color" /> + <!-- Blending mode used to apply the button graphic tint. --> + <attr name="buttonTintMode"> + <!-- The tint is drawn on top of the drawable. + [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] --> + <enum name="src_over" value="3" /> + <!-- The tint is masked by the alpha channel of the drawable. The drawable’s + color channels are thrown out. [Sa * Da, Sc * Da] --> + <enum name="src_in" value="5" /> + <!-- The tint is drawn above the drawable, but with the drawable’s alpha + channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] --> + <enum name="src_atop" value="9" /> + <!-- Multiplies the color and alpha channels of the drawable with those of + the tint. [Sa * Da, Sc * Dc] --> + <enum name="multiply" value="14" /> + <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] --> + <enum name="screen" value="15" /> + <!-- Combines the tint and drawable color and alpha channels, clamping the + result to valid color values. Saturate(S + D) --> + <enum name="add" value="16" /> + </attr> </declare-styleable> <declare-styleable name="CheckedTextView"> <!-- Indicates the initial checked state of this text. --> @@ -3106,6 +3152,28 @@ <!-- Determines whether to measure all children or just those in the VISIBLE or INVISIBLE state when measuring. Defaults to false. --> <attr name="measureAllChildren" format="boolean" /> + <!-- Tint to apply to the foreground. --> + <attr name="foregroundTint" format="color" /> + <!-- Blending mode used to apply the foreground tint. --> + <attr name="foregroundTintMode"> + <!-- The tint is drawn on top of the drawable. + [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] --> + <enum name="src_over" value="3" /> + <!-- The tint is masked by the alpha channel of the drawable. The drawable’s + color channels are thrown out. [Sa * Da, Sc * Da] --> + <enum name="src_in" value="5" /> + <!-- The tint is drawn above the drawable, but with the drawable’s alpha + channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] --> + <enum name="src_atop" value="9" /> + <!-- Multiplies the color and alpha channels of the drawable with those of + the tint. [Sa * Da, Sc * Dc] --> + <enum name="multiply" value="14" /> + <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] --> + <enum name="screen" value="15" /> + <!-- Combines the tint and drawable color and alpha channels, clamping the + result to valid color values. Saturate(S + D) --> + <enum name="add" value="16" /> + </attr> </declare-styleable> <declare-styleable name="ExpandableListView"> <!-- Indicator shown beside the group View. This can be a stateful Drawable. --> @@ -3211,6 +3279,10 @@ <!-- @hide The alpha value (0-255) set on the ImageView's drawable. Equivalent to calling ImageView.setAlpha(int), not the same as View.setAlpha(float). --> <attr name="drawableAlpha" format="integer" /> + <!-- Tint to apply to the image. --> + <attr name="tint" /> + <!-- Blending mode used to apply the image tint. --> + <attr name="tintMode" /> </declare-styleable> <declare-styleable name="ToggleButton"> <!-- The text for the button when it is checked. --> @@ -3401,6 +3473,98 @@ <!-- Defines if the associated drawables need to be mirrored when in RTL mode. Default is false --> <attr name="mirrorForRtl" format="boolean" /> + <!-- Tint to apply to the progress indicator. --> + <attr name="progressTint" format="color" /> + <!-- Blending mode used to apply the progress indicator tint. --> + <attr name="progressTintMode"> + <!-- The tint is drawn on top of the drawable. + [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] --> + <enum name="src_over" value="3" /> + <!-- The tint is masked by the alpha channel of the drawable. The drawable’s + color channels are thrown out. [Sa * Da, Sc * Da] --> + <enum name="src_in" value="5" /> + <!-- The tint is drawn above the drawable, but with the drawable’s alpha + channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] --> + <enum name="src_atop" value="9" /> + <!-- Multiplies the color and alpha channels of the drawable with those of + the tint. [Sa * Da, Sc * Dc] --> + <enum name="multiply" value="14" /> + <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] --> + <enum name="screen" value="15" /> + <!-- Combines the tint and drawable color and alpha channels, clamping the + result to valid color values. Saturate(S + D) --> + <enum name="add" value="16" /> + </attr> + <!-- Tint to apply to the progress indicator background. --> + <attr name="progressBackgroundTint" format="color" /> + <!-- Blending mode used to apply the progress indicator background tint. --> + <attr name="progressBackgroundTintMode"> + <!-- The tint is drawn on top of the drawable. + [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] --> + <enum name="src_over" value="3" /> + <!-- The tint is masked by the alpha channel of the drawable. The drawable’s + color channels are thrown out. [Sa * Da, Sc * Da] --> + <enum name="src_in" value="5" /> + <!-- The tint is drawn above the drawable, but with the drawable’s alpha + channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] --> + <enum name="src_atop" value="9" /> + <!-- Multiplies the color and alpha channels of the drawable with those of + the tint. [Sa * Da, Sc * Dc] --> + <enum name="multiply" value="14" /> + <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] --> + <enum name="screen" value="15" /> + <!-- Combines the tint and drawable color and alpha channels, clamping the + result to valid color values. Saturate(S + D) --> + <enum name="add" value="16" /> + </attr> + <!-- Tint to apply to the secondary progress indicator. --> + <attr name="secondaryProgressTint" format="color" /> + <!-- Blending mode used to apply the secondary progress indicator tint. --> + <attr name="secondaryProgressTintMode"> + <!-- The tint is drawn on top of the drawable. + [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] --> + <enum name="src_over" value="3" /> + <!-- The tint is masked by the alpha channel of the drawable. The drawable’s + color channels are thrown out. [Sa * Da, Sc * Da] --> + <enum name="src_in" value="5" /> + <!-- The tint is drawn above the drawable, but with the drawable’s alpha + channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] --> + <enum name="src_atop" value="9" /> + <!-- Multiplies the color and alpha channels of the drawable with those of + the tint. [Sa * Da, Sc * Dc] --> + <enum name="multiply" value="14" /> + <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] --> + <enum name="screen" value="15" /> + <!-- Combines the tint and drawable color and alpha channels, clamping the + result to valid color values. Saturate(S + D) --> + <enum name="add" value="16" /> + </attr> + <!-- Tint to apply to the indepterminate progress indicator. --> + <attr name="indeterminateTint" format="color" /> + <!-- Blending mode used to apply the indeterminate progress indicator tint. --> + <attr name="indeterminateTintMode"> + <!-- The tint is drawn on top of the drawable. + [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] --> + <enum name="src_over" value="3" /> + <!-- The tint is masked by the alpha channel of the drawable. The drawable’s + color channels are thrown out. [Sa * Da, Sc * Da] --> + <enum name="src_in" value="5" /> + <!-- The tint is drawn above the drawable, but with the drawable’s alpha + channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] --> + <enum name="src_atop" value="9" /> + <!-- Multiplies the color and alpha channels of the drawable with those of + the tint. [Sa * Da, Sc * Dc] --> + <enum name="multiply" value="14" /> + <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] --> + <enum name="screen" value="15" /> + <!-- Combines the tint and drawable color and alpha channels, clamping the + result to valid color values. Saturate(S + D) --> + <enum name="add" value="16" /> + </attr> + <!-- Tint to apply to the background. --> + <attr name="backgroundTint" /> + <!-- Blending mode used to apply the background tint. --> + <attr name="backgroundTintMode" /> </declare-styleable> <declare-styleable name="SeekBar"> @@ -3410,6 +3574,28 @@ <attr name="thumbOffset" format="dimension" /> <!-- Whether to split the track and leave a gap for the thumb drawable. --> <attr name="splitTrack" format="boolean" /> + <!-- Tint to apply to the button graphic. --> + <attr name="thumbTint" format="color" /> + <!-- Blending mode used to apply the button graphic tint. --> + <attr name="thumbTintMode"> + <!-- The tint is drawn on top of the drawable. + [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] --> + <enum name="src_over" value="3" /> + <!-- The tint is masked by the alpha channel of the drawable. The drawable’s + color channels are thrown out. [Sa * Da, Sc * Da] --> + <enum name="src_in" value="5" /> + <!-- The tint is drawn above the drawable, but with the drawable’s alpha + channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] --> + <enum name="src_atop" value="9" /> + <!-- Multiplies the color and alpha channels of the drawable with those of + the tint. [Sa * Da, Sc * Dc] --> + <enum name="multiply" value="14" /> + <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] --> + <enum name="screen" value="15" /> + <!-- Combines the tint and drawable color and alpha channels, clamping the + result to valid color values. Saturate(S + D) --> + <enum name="add" value="16" /> + </attr> </declare-styleable> <declare-styleable name="StackView"> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 202c1271ec20..1580d690f630 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2190,6 +2190,22 @@ <public type="attr" name="searchKeyphraseSupportedLocales" /> <public type="attr" name="windowTransitionBackgroundFadeDuration" /> <public type="attr" name="overlapAnchor" /> + <public type="attr" name="progressTint" /> + <public type="attr" name="progressTintMode" /> + <public type="attr" name="progressBackgroundTint" /> + <public type="attr" name="progressBackgroundTintMode" /> + <public type="attr" name="secondaryProgressTint" /> + <public type="attr" name="secondaryProgressTintMode" /> + <public type="attr" name="indeterminateTint" /> + <public type="attr" name="indeterminateTintMode" /> + <public type="attr" name="backgroundTint" /> + <public type="attr" name="backgroundTintMode" /> + <public type="attr" name="foregroundTint" /> + <public type="attr" name="foregroundTintMode" /> + <public type="attr" name="buttonTint" /> + <public type="attr" name="buttonTintMode" /> + <public type="attr" name="thumbTint" /> + <public type="attr" name="thumbTintMode" /> <public-padding type="dimen" name="l_resource_pad" end="0x01050010" /> diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index cb88e3da28ad..40b55a7f0afe 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -1260,8 +1260,10 @@ public abstract class Drawable { /** * Parses a {@link android.graphics.PorterDuff.Mode} from a tintMode * attribute's enum value. + * + * @hide */ - static PorterDuff.Mode parseTintMode(int value, Mode defaultMode) { + public static PorterDuff.Mode parseTintMode(int value, Mode defaultMode) { switch (value) { case 3: return Mode.SRC_OVER; case 5: return Mode.SRC_IN; |