mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-04-28 12:17:57 +03:00
api-impl: add ClipDrawable from AOSP
taken from AOSP master (commit ed8c91e410671fa153f1587f61d05b303bf94f95)
This commit is contained in:
parent
bf79a77993
commit
df03617f13
3 changed files with 800 additions and 6 deletions
238
src/api-impl/android/graphics/drawable/ClipDrawable.java
Normal file
238
src/api-impl/android/graphics/drawable/ClipDrawable.java
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Copyright (C) 2006 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.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
//import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import com.android.internal.R;
|
||||
import java.io.IOException;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
/**
|
||||
* A Drawable that clips another Drawable based on this Drawable's current
|
||||
* level value. You can control how much the child Drawable gets clipped in width
|
||||
* and height based on the level, as well as a gravity to control where it is
|
||||
* placed in its overall container. Most often used to implement things like
|
||||
* progress bars, by increasing the drawable's level with {@link
|
||||
* android.graphics.drawable.Drawable#setLevel(int) setLevel()}.
|
||||
* <p class="note"><strong>Note:</strong> The drawable is clipped completely and not visible when
|
||||
* the level is 0 and fully revealed when the level is 10,000.</p>
|
||||
*
|
||||
* <p>It can be defined in an XML file with the <code><clip></code> element. For more
|
||||
* information, see the guide to <a
|
||||
* href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
|
||||
*
|
||||
* @attr ref android.R.styleable#ClipDrawable_clipOrientation
|
||||
* @attr ref android.R.styleable#ClipDrawable_gravity
|
||||
* @attr ref android.R.styleable#ClipDrawable_drawable
|
||||
*/
|
||||
public class ClipDrawable extends DrawableWrapper {
|
||||
public static final int HORIZONTAL = 1;
|
||||
public static final int VERTICAL = 2;
|
||||
|
||||
private static final int MAX_LEVEL = 10000;
|
||||
|
||||
private final Rect mTmpRect = new Rect();
|
||||
|
||||
//@UnsupportedAppUsage
|
||||
private ClipState mState;
|
||||
|
||||
ClipDrawable() {
|
||||
this(new ClipState(null, null), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new clip drawable with the specified gravity and orientation.
|
||||
*
|
||||
* @param drawable the drawable to clip
|
||||
* @param gravity gravity constant (see {@link Gravity} used to position
|
||||
* the clipped drawable within the parent container
|
||||
* @param orientation bitwise-or of {@link #HORIZONTAL} and/or
|
||||
* {@link #VERTICAL}
|
||||
*/
|
||||
public ClipDrawable(Drawable drawable, int gravity, int orientation) {
|
||||
this(new ClipState(null, null), null);
|
||||
|
||||
mState.mGravity = gravity;
|
||||
mState.mOrientation = orientation;
|
||||
|
||||
setDrawable(drawable);
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ClipDrawable);
|
||||
|
||||
// Inflation will advance the XmlPullParser and AttributeSet.
|
||||
super.inflate(r, parser, attrs, theme);
|
||||
|
||||
updateStateFromTypedArray(a);
|
||||
verifyRequiredAttributes(a);
|
||||
a.recycle();
|
||||
}*/
|
||||
|
||||
/*@Override
|
||||
public void applyTheme(@NonNull Theme t) {
|
||||
super.applyTheme(t);
|
||||
|
||||
final ClipState state = mState;
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.mThemeAttrs != null) {
|
||||
final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ClipDrawable);
|
||||
try {
|
||||
updateStateFromTypedArray(a);
|
||||
verifyRequiredAttributes(a);
|
||||
} catch (XmlPullParserException e) {
|
||||
rethrowAsRuntimeException(e);
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
private void verifyRequiredAttributes(@NonNull TypedArray a) throws XmlPullParserException {
|
||||
// If we're not waiting on a theme, verify required attributes.
|
||||
if (getDrawable() == null && (mState.mThemeAttrs == null || mState.mThemeAttrs[R.styleable.ClipDrawable_drawable] == 0)) {
|
||||
throw new XmlPullParserException(a.getPositionDescription() + ": <clip> tag requires a 'drawable' attribute or "
|
||||
+ "child tag defining a drawable");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStateFromTypedArray(@NonNull TypedArray a) {
|
||||
final ClipState state = mState;
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Account for any configuration changes.
|
||||
//state.mChangingConfigurations |= a.getChangingConfigurations();
|
||||
|
||||
// Extract the theme attributes, if any.
|
||||
state.mThemeAttrs = a.extractThemeAttrs();
|
||||
|
||||
state.mOrientation = a.getInt(
|
||||
R.styleable.ClipDrawable_clipOrientation, state.mOrientation);
|
||||
state.mGravity = a.getInt(
|
||||
R.styleable.ClipDrawable_gravity, state.mGravity);
|
||||
}
|
||||
|
||||
/*@Override
|
||||
protected boolean onLevelChange(int level) {
|
||||
super.onLevelChange(level);
|
||||
invalidateSelf();
|
||||
return true;
|
||||
}*/
|
||||
|
||||
/*@Override
|
||||
public int getOpacity() {
|
||||
final Drawable dr = getDrawable();
|
||||
final int opacity = dr.getOpacity();
|
||||
if (opacity == PixelFormat.TRANSPARENT || dr.getLevel() == 0) {
|
||||
return PixelFormat.TRANSPARENT;
|
||||
}
|
||||
|
||||
final int level = getLevel();
|
||||
if (level >= MAX_LEVEL) {
|
||||
return dr.getOpacity();
|
||||
}
|
||||
|
||||
// Some portion of non-transparent drawable is showing.
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
final Drawable dr = getDrawable();
|
||||
if (dr.getLevel() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Rect r = mTmpRect;
|
||||
final Rect bounds = getBounds();
|
||||
final int level = getLevel();
|
||||
|
||||
int w = bounds.width();
|
||||
final int iw = 0; // mState.mDrawable.getIntrinsicWidth();
|
||||
if ((mState.mOrientation & HORIZONTAL) != 0) {
|
||||
w -= (w - iw) * (MAX_LEVEL - level) / MAX_LEVEL;
|
||||
}
|
||||
|
||||
int h = bounds.height();
|
||||
final int ih = 0; // mState.mDrawable.getIntrinsicHeight();
|
||||
if ((mState.mOrientation & VERTICAL) != 0) {
|
||||
h -= (h - ih) * (MAX_LEVEL - level) / MAX_LEVEL;
|
||||
}
|
||||
|
||||
//final int layoutDirection = getLayoutDirection();
|
||||
//Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection);
|
||||
|
||||
if (w > 0 && h > 0) {
|
||||
canvas.save();
|
||||
canvas.clipRect(r);
|
||||
dr.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
/*@Override
|
||||
DrawableWrapperState mutateConstantState() {
|
||||
mState = new ClipState(mState, null);
|
||||
return mState;
|
||||
}*/
|
||||
|
||||
static final class ClipState extends DrawableWrapper.DrawableWrapperState {
|
||||
private int[] mThemeAttrs;
|
||||
|
||||
int mOrientation = HORIZONTAL;
|
||||
int mGravity = Gravity.LEFT;
|
||||
|
||||
ClipState(ClipState orig, Resources res) {
|
||||
super(orig, res);
|
||||
|
||||
if (orig != null) {
|
||||
mOrientation = orig.mOrientation;
|
||||
mGravity = orig.mGravity;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable(Resources res) {
|
||||
return new ClipDrawable(this, res);
|
||||
}
|
||||
}
|
||||
|
||||
private ClipDrawable(ClipState state, Resources res) {
|
||||
super(state, res);
|
||||
|
||||
mState = state;
|
||||
}
|
||||
}
|
|
@ -268,6 +268,14 @@ public class Drawable {
|
|||
return new Drawable(paintable);
|
||||
}
|
||||
|
||||
public static Drawable createFromPath(String path) {
|
||||
if (path == null)
|
||||
return null;
|
||||
|
||||
long paintable = native_paintable_from_path(path);
|
||||
return new Drawable(paintable);
|
||||
}
|
||||
|
||||
protected boolean onStateChange(int[] stateSet) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,563 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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.graphics.drawable.Drawable;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
//import android.compat.annotation.UnsupportedAppUsage;
|
||||
//import android.content.pm.ActivityInfo.Config;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.content.res.TypedArray;
|
||||
//import android.graphics.BlendMode;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
//import android.graphics.Insets;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Xfermode;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import com.android.internal.R;
|
||||
import java.io.IOException;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
public class DrawableWrapper extends Drawable {
|
||||
private Drawable drawable;
|
||||
/**
|
||||
* Drawable container with only one child element.
|
||||
*/
|
||||
public abstract class DrawableWrapper extends Drawable implements Drawable.Callback {
|
||||
//@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
private DrawableWrapperState mState;
|
||||
private Drawable mDrawable;
|
||||
private boolean mMutated;
|
||||
|
||||
public DrawableWrapper(Drawable drawable) {
|
||||
this.drawable = drawable;
|
||||
DrawableWrapper(DrawableWrapperState state, Resources res) {
|
||||
mState = state;
|
||||
|
||||
updateLocalState(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new wrapper around the specified drawable.
|
||||
*
|
||||
* @param dr the drawable to wrap
|
||||
*/
|
||||
public DrawableWrapper(@Nullable Drawable dr) {
|
||||
mState = null;
|
||||
setDrawable(dr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes local dynamic properties from state. This should be called
|
||||
* after significant state changes, e.g. from the One True Constructor and
|
||||
* after inflating or applying a theme.
|
||||
*/
|
||||
private void updateLocalState(Resources res) {
|
||||
if (mState != null && mState.mDrawableState != null) {
|
||||
final Drawable dr = mState.mDrawableState.newDrawable(res);
|
||||
setDrawable(dr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
/*@Override
|
||||
public void setXfermode(Xfermode mode) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setXfermode(mode);
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Sets the wrapped drawable.
|
||||
*
|
||||
* @param dr the wrapped drawable
|
||||
*/
|
||||
public void setDrawable(@Nullable Drawable dr) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setCallback(null);
|
||||
}
|
||||
|
||||
mDrawable = dr;
|
||||
|
||||
if (dr != null) {
|
||||
dr.setCallback(this);
|
||||
|
||||
// Only call setters for data that's stored in the base Drawable.
|
||||
dr.setVisible(isVisible(), true);
|
||||
dr.setState(getState());
|
||||
dr.setLevel(getLevel());
|
||||
dr.setBounds(getBounds());
|
||||
//dr.setLayoutDirection(getLayoutDirection());
|
||||
|
||||
if (mState != null) {
|
||||
mState.mDrawableState = dr.getConstantState();
|
||||
}
|
||||
}
|
||||
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the wrapped drawable
|
||||
*/
|
||||
@Nullable
|
||||
public Drawable getDrawable() {
|
||||
return drawable;
|
||||
return mDrawable;
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
super.inflate(r, parser, attrs, theme);
|
||||
|
||||
final DrawableWrapperState state = mState;
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The density may have changed since the last update. This will
|
||||
// apply scaling to any existing constant state properties.
|
||||
final int densityDpi = r.getDisplayMetrics().densityDpi;
|
||||
final int targetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi;
|
||||
state.setDensity(targetDensity);
|
||||
state.mSrcDensityOverride = mSrcDensityOverride;
|
||||
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.DrawableWrapper);
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
|
||||
inflateChildDrawable(r, parser, attrs, theme);
|
||||
}*/
|
||||
|
||||
/*@Override
|
||||
public void applyTheme(@NonNull Theme t) {
|
||||
super.applyTheme(t);
|
||||
|
||||
// If we load the drawable later as part of updating from the typed
|
||||
// array, it will already be themed correctly. So, we can theme the
|
||||
// local drawable first.
|
||||
if (mDrawable != null && mDrawable.canApplyTheme()) {
|
||||
mDrawable.applyTheme(t);
|
||||
}
|
||||
|
||||
final DrawableWrapperState state = mState;
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int densityDpi = t.getResources().getDisplayMetrics().densityDpi;
|
||||
final int density = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi;
|
||||
state.setDensity(density);
|
||||
|
||||
if (state.mThemeAttrs != null) {
|
||||
final TypedArray a = t.resolveAttributes(
|
||||
state.mThemeAttrs, R.styleable.DrawableWrapper);
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Updates constant state properties from the provided typed array.
|
||||
* <p>
|
||||
* Implementing subclasses should call through to the super method first.
|
||||
*
|
||||
* @param a the typed array rom which properties should be read
|
||||
*/
|
||||
private void updateStateFromTypedArray(@NonNull TypedArray a) {
|
||||
final DrawableWrapperState state = mState;
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Account for any configuration changes.
|
||||
state.mChangingConfigurations |= a.getChangingConfigurations();
|
||||
|
||||
// Extract the theme attributes, if any.
|
||||
state.mThemeAttrs = a.extractThemeAttrs();
|
||||
|
||||
if (a.hasValueOrEmpty(R.styleable.DrawableWrapper_drawable)) {
|
||||
setDrawable(a.getDrawable(R.styleable.DrawableWrapper_drawable));
|
||||
}
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public boolean canApplyTheme() {
|
||||
return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public void invalidateDrawable(@NonNull Drawable who) {
|
||||
final Callback callback = getCallback();
|
||||
if (callback != null) {
|
||||
callback.invalidateDrawable(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
|
||||
final Callback callback = getCallback();
|
||||
if (callback != null) {
|
||||
callback.scheduleDrawable(this, what, when);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
|
||||
final Callback callback = getCallback();
|
||||
if (callback != null) {
|
||||
callback.unscheduleDrawable(this, what);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public /*@Config*/ int getChangingConfigurations() {
|
||||
return super.getChangingConfigurations() | (mState != null ? mState.getChangingConfigurations() : 0) | mDrawable.getChangingConfigurations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPadding(@NonNull Rect padding) {
|
||||
return mDrawable != null && mDrawable.getPadding(padding);
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public Insets getOpticalInsets() {
|
||||
return mDrawable != null ? mDrawable.getOpticalInsets() : Insets.NONE;
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public void setHotspot(float x, float y) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setHotspot(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public void setHotspotBounds(int left, int top, int right, int bottom) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setHotspotBounds(left, top, right, bottom);
|
||||
}
|
||||
}*/
|
||||
|
||||
/*@Override
|
||||
public void getHotspotBounds(@NonNull Rect outRect) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.getHotspotBounds(outRect);
|
||||
} else {
|
||||
outRect.set(getBounds());
|
||||
}
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public boolean setVisible(boolean visible, boolean restart) {
|
||||
final boolean superChanged = super.setVisible(visible, restart);
|
||||
final boolean changed = mDrawable != null && mDrawable.setVisible(visible, restart);
|
||||
return superChanged | changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public int getAlpha() {
|
||||
return mDrawable != null ? mDrawable.getAlpha() : 255;
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setColorFilter(colorFilter);
|
||||
}
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public ColorFilter getColorFilter() {
|
||||
final Drawable drawable = getDrawable();
|
||||
if (drawable != null) {
|
||||
return drawable.getColorFilter();
|
||||
}
|
||||
return super.getColorFilter();
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public void setTintList(@Nullable ColorStateList tint) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setTintList(tint);
|
||||
}
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public void setTintBlendMode(@NonNull BlendMode blendMode) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setTintBlendMode(blendMode);
|
||||
}
|
||||
}*/
|
||||
|
||||
/*@Override
|
||||
public boolean onLayoutDirectionChanged(@View.ResolvedLayoutDir int layoutDirection) {
|
||||
return mDrawable != null && mDrawable.setLayoutDirection(layoutDirection);
|
||||
}*/
|
||||
|
||||
/*@Override
|
||||
public int getOpacity() {
|
||||
return mDrawable != null ? mDrawable.getOpacity() : PixelFormat.TRANSPARENT;
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public boolean isStateful() {
|
||||
return mDrawable != null && mDrawable.isStateful();
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public boolean hasFocusStateSpecified() {
|
||||
return mDrawable != null && mDrawable.hasFocusStateSpecified();
|
||||
}*/
|
||||
|
||||
@Override
|
||||
protected boolean onStateChange(@NonNull int[] state) {
|
||||
if (mDrawable != null && mDrawable.isStateful()) {
|
||||
final boolean changed = mDrawable.setState(state);
|
||||
if (changed) {
|
||||
onBoundsChange(getBounds());
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jumpToCurrentState() {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.jumpToCurrentState();
|
||||
}
|
||||
}
|
||||
|
||||
/*@Override
|
||||
protected boolean onLevelChange(int level) {
|
||||
return mDrawable != null && mDrawable.setLevel(level);
|
||||
}*/
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(@NonNull Rect bounds) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setBounds(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mDrawable != null ? mDrawable.getIntrinsicWidth() : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return mDrawable != null ? mDrawable.getIntrinsicHeight() : -1;
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public void getOutline(@NonNull Outline outline) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.getOutline(outline);
|
||||
} else {
|
||||
super.getOutline(outline);
|
||||
}
|
||||
}*/
|
||||
|
||||
/*@Override
|
||||
@Nullable
|
||||
public ConstantState getConstantState() {
|
||||
if (mState != null && mState.canConstantState()) {
|
||||
mState.mChangingConfigurations = getChangingConfigurations();
|
||||
return mState;
|
||||
}
|
||||
return null;
|
||||
}*/
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Drawable mutate() {
|
||||
if (!mMutated && super.mutate() == this) {
|
||||
mState = mutateConstantState();
|
||||
if (mDrawable != null) {
|
||||
mDrawable.mutate();
|
||||
}
|
||||
if (mState != null) {
|
||||
mState.mDrawableState = mDrawable != null ? mDrawable.getConstantState() : null;
|
||||
}
|
||||
mMutated = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutates the constant state and returns the new state. Responsible for
|
||||
* updating any local copy.
|
||||
* <p>
|
||||
* This method should never call the super implementation; it should always
|
||||
* mutate and return its own constant state.
|
||||
*
|
||||
* @return the new state
|
||||
*/
|
||||
DrawableWrapperState mutateConstantState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide Only used by the framework for pre-loading resources.
|
||||
*/
|
||||
/*public void clearMutated() {
|
||||
super.clearMutated();
|
||||
if (mDrawable != null) {
|
||||
mDrawable.clearMutated();
|
||||
}
|
||||
mMutated = false;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Called during inflation to inflate the child element. The last valid
|
||||
* child element will take precedence over any other child elements or
|
||||
* explicit drawable attribute.
|
||||
*/
|
||||
/* void inflateChildDrawable(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
// Seek to the first child element.
|
||||
Drawable dr = null;
|
||||
int type;
|
||||
final int outerDepth = parser.getDepth();
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||
if (type == XmlPullParser.START_TAG) {
|
||||
dr = Drawable.createFromXmlInnerForDensity(r, parser, attrs,
|
||||
mState.mSrcDensityOverride, theme);
|
||||
}
|
||||
}
|
||||
|
||||
if (dr != null) {
|
||||
setDrawable(dr);
|
||||
}
|
||||
}*/
|
||||
|
||||
abstract static class DrawableWrapperState extends Drawable.ConstantState {
|
||||
private int[] mThemeAttrs;
|
||||
|
||||
//@Config
|
||||
int mChangingConfigurations;
|
||||
int mDensity = DisplayMetrics.DENSITY_DEFAULT;
|
||||
|
||||
/**
|
||||
* The density to use when looking up resources from
|
||||
* {@link Resources#getDrawableForDensity(int, int, Theme)}.
|
||||
* A value of 0 means there is no override and the system density will be used.
|
||||
* @hide
|
||||
*/
|
||||
int mSrcDensityOverride = 0;
|
||||
|
||||
Drawable.ConstantState mDrawableState;
|
||||
|
||||
DrawableWrapperState(@Nullable DrawableWrapperState orig, @Nullable Resources res) {
|
||||
if (orig != null) {
|
||||
mThemeAttrs = orig.mThemeAttrs;
|
||||
mChangingConfigurations = orig.mChangingConfigurations;
|
||||
mDrawableState = orig.mDrawableState;
|
||||
mSrcDensityOverride = orig.mSrcDensityOverride;
|
||||
}
|
||||
|
||||
final int density;
|
||||
if (res != null) {
|
||||
density = res.getDisplayMetrics().densityDpi;
|
||||
} else if (orig != null) {
|
||||
density = orig.mDensity;
|
||||
} else {
|
||||
density = 0;
|
||||
}
|
||||
|
||||
mDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the constant state density.
|
||||
* <p>
|
||||
* If the density has been previously set, dispatches the change to
|
||||
* subclasses so that density-dependent properties may be scaled as
|
||||
* necessary.
|
||||
*
|
||||
* @param targetDensity the new constant state density
|
||||
*/
|
||||
public final void setDensity(int targetDensity) {
|
||||
if (mDensity != targetDensity) {
|
||||
final int sourceDensity = mDensity;
|
||||
mDensity = targetDensity;
|
||||
|
||||
onDensityChanged(sourceDensity, targetDensity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the constant state density changes.
|
||||
* <p>
|
||||
* Subclasses with density-dependent constant state properties should
|
||||
* override this method and scale their properties as necessary.
|
||||
*
|
||||
* @param sourceDensity the previous constant state density
|
||||
* @param targetDensity the new constant state density
|
||||
*/
|
||||
void onDensityChanged(int sourceDensity, int targetDensity) {
|
||||
// Stub method.
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public boolean canApplyTheme() {
|
||||
return mThemeAttrs != null || (mDrawableState != null && mDrawableState.canApplyTheme()) || super.canApplyTheme();
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable() {
|
||||
return newDrawable(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract Drawable newDrawable(@Nullable Resources res);
|
||||
|
||||
@Override
|
||||
public /*@Config*/ int getChangingConfigurations() {
|
||||
return mChangingConfigurations | (mDrawableState != null ? mDrawableState.getChangingConfigurations() : 0);
|
||||
}
|
||||
|
||||
public boolean canConstantState() {
|
||||
return mDrawableState != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue