diff options
| author | 2018-08-22 20:00:42 +0000 | |
|---|---|---|
| committer | 2018-08-22 20:00:42 +0000 | |
| commit | 6c5670577a1c08baeb822bc4803ab56a3653ef9a (patch) | |
| tree | e022f6759a7c9cd65d45ba046b49a67e34c7ad28 | |
| parent | b9d8b91e7a94ee6e7c5c65fd3f667d65ba557e91 (diff) | |
| parent | e3b135743f8cbfe131f4db314f986ab76e5d0be9 (diff) | |
Merge "Create ColorStateListDrawable"
| -rw-r--r-- | core/java/android/content/res/ResourcesImpl.java | 32 | ||||
| -rw-r--r-- | graphics/java/android/graphics/drawable/ColorStateListDrawable.java | 271 |
2 files changed, 290 insertions, 13 deletions
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java index 19e399a50724..b644e23223b7 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -1,17 +1,17 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package android.content.res; @@ -35,6 +35,7 @@ import android.graphics.Bitmap; import android.graphics.ImageDecoder; import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.ColorStateListDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.DrawableContainer; import android.icu.text.PluralRules; @@ -846,10 +847,15 @@ public class ResourcesImpl { stack.push(id); try { if (file.endsWith(".xml")) { - final XmlResourceParser rp = loadXmlResourceParser( - file, id, value.assetCookie, "drawable"); - dr = Drawable.createFromXmlForDensity(wrapper, rp, density, null); - rp.close(); + if (file.startsWith("res/color/")) { + ColorStateList csl = loadColorStateList(wrapper, value, id, null); + dr = (csl != null ? new ColorStateListDrawable(csl) : null); + } else { + final XmlResourceParser rp = loadXmlResourceParser( + file, id, value.assetCookie, "drawable"); + dr = Drawable.createFromXmlForDensity(wrapper, rp, density, null); + rp.close(); + } } else { final InputStream is = mAssets.openNonAsset( value.assetCookie, file, AssetManager.ACCESS_STREAMING); diff --git a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java new file mode 100644 index 000000000000..40ba5d159261 --- /dev/null +++ b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java @@ -0,0 +1,271 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.graphics.drawable; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.content.pm.ActivityInfo; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.util.MathUtils; + +/** + * A Drawable that manages a {@link ColorDrawable} to make it stateful and backed by a + * {@link ColorStateList}. + */ +public class ColorStateListDrawable extends Drawable implements Drawable.Callback { + private ColorDrawable mColorDrawable; + private ColorStateListDrawableState mState; + + public ColorStateListDrawable() { + mState = new ColorStateListDrawableState(); + initializeColorDrawable(); + } + + public ColorStateListDrawable(ColorStateList colorStateList) { + mState = new ColorStateListDrawableState(); + initializeColorDrawable(); + setColorStateList(colorStateList); + } + + @Override + public void draw(Canvas canvas) { + mColorDrawable.draw(canvas); + } + + @Override + @IntRange(from = 0, to = 255) + public int getAlpha() { + return mColorDrawable.getAlpha(); + } + + @Override + public boolean isStateful() { + return mState.isStateful(); + } + + @Override + public boolean hasFocusStateSpecified() { + return mState.hasFocusStateSpecified(); + } + + @Override + public @NonNull Drawable getCurrent() { + return mColorDrawable; + } + + @Override + public void applyTheme(Resources.Theme t) { + super.applyTheme(t); + + if (mState.mColor != null) { + setColorStateList(mState.mColor.obtainForTheme(t)); + } + + if (mState.mTint != null) { + setTintList(mState.mTint.obtainForTheme(t)); + } + } + + @Override + public boolean canApplyTheme() { + return super.canApplyTheme() || mState.canApplyTheme(); + } + + @Override + public void setAlpha(@IntRange(from = 0, to = 255) int alpha) { + mState.mAlpha = alpha; + onStateChange(getState()); + } + + /** + * Remove the alpha override, reverting to the alpha defined on each color in the + * {@link ColorStateList}. + */ + public void clearAlpha() { + mState.mAlpha = -1; + onStateChange(getState()); + } + + @Override + public void setTintList(ColorStateList tint) { + mState.mTint = tint; + mColorDrawable.setTintList(tint); + onStateChange(getState()); + } + + @Override + public void setTintMode(PorterDuff.Mode tintMode) { + mState.mTintMode = tintMode; + mColorDrawable.setTintMode(tintMode); + onStateChange(getState()); + } + + @Override + public ColorFilter getColorFilter() { + return mColorDrawable.getColorFilter(); + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + mColorDrawable.setColorFilter(colorFilter); + } + + @Override + public @PixelFormat.Opacity int getOpacity() { + return mColorDrawable.getOpacity(); + } + + @Override + protected boolean onStateChange(int[] state) { + if (mState.mColor != null) { + int color = mState.mColor.getColorForState(state, mState.mColor.getDefaultColor()); + + if (mState.mAlpha != -1) { + color = color & 0xFFFFFF | MathUtils.constrain(mState.mAlpha, 0, 255) << 24; + } + + if (color != mColorDrawable.getColor()) { + mColorDrawable.setColor(color); + mColorDrawable.setState(state); + return true; + } else { + return mColorDrawable.setState(state); + } + } else { + return false; + } + } + + @Override + public void invalidateDrawable(Drawable who) { + final Callback callback = getCallback(); + + if (callback != null) { + callback.invalidateDrawable(who); + } + } + + @Override + public void scheduleDrawable(Drawable who, Runnable what, long when) { + final Callback callback = getCallback(); + + if (callback != null) { + callback.scheduleDrawable(who, what, when); + } + } + + @Override + public void unscheduleDrawable(Drawable who, Runnable what) { + final Callback callback = getCallback(); + + if (callback != null) { + callback.unscheduleDrawable(who, what); + } + } + + @Override + public ConstantState getConstantState() { + return mState; + } + + /** + * Returns the ColorStateList backing this Drawable, or a new ColorStateList of the default + * ColorDrawable color if one hasn't been defined yet. + * + * @return a ColorStateList + */ + public @NonNull ColorStateList getColorStateList() { + if (mState.mColor == null) { + return ColorStateList.valueOf(mColorDrawable.getColor()); + } else { + return mState.mColor; + } + } + + /** + * Replace this Drawable's ColorStateList. It is not copied, so changes will propagate on the + * next call to {@link #setState(int[])}. + * + * @param colorStateList A color state list to attach. + */ + public void setColorStateList(ColorStateList colorStateList) { + mState.mColor = colorStateList; + onStateChange(getState()); + } + + static final class ColorStateListDrawableState extends ConstantState { + ColorStateList mColor = null; + ColorStateList mTint = null; + int mAlpha = -1; + PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; + @ActivityInfo.Config int mChangingConfigurations = 0; + + ColorStateListDrawableState() { + } + + + @Override + public Drawable newDrawable() { + return new ColorStateListDrawable(this); + } + + @Override + public @ActivityInfo.Config int getChangingConfigurations() { + return mChangingConfigurations + | (mColor != null ? mColor.getChangingConfigurations() : 0) + | (mTint != null ? mTint.getChangingConfigurations() : 0); + } + + public boolean isStateful() { + return (mColor != null && mColor.isStateful()) + || (mTint != null && mTint.isStateful()); + } + + public boolean hasFocusStateSpecified() { + return (mColor != null && mColor.hasFocusStateSpecified()) + || (mTint != null && mTint.hasFocusStateSpecified()); + } + + @Override + public boolean canApplyTheme() { + return (mColor != null && mColor.canApplyTheme()) + || (mTint != null && mTint.canApplyTheme()); + } + } + + private ColorStateListDrawable(ColorStateListDrawableState state) { + mState = state; + initializeColorDrawable(); + } + + private void initializeColorDrawable() { + mColorDrawable = new ColorDrawable(); + mColorDrawable.setCallback(this); + + if (mState.mTint != null) { + mColorDrawable.setTintList(mState.mTint); + } + + if (mState.mTintMode != DEFAULT_TINT_MODE) { + mColorDrawable.setTintMode(mState.mTintMode); + } + } +} |