Add an new internal DrawableContainer to handle animation scale == 0 case.
am: 0c03664fa6
Change-Id: I7feae01c6302e2942087c6dfe1948109467f1326
This commit is contained in:
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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 com.android.internal.graphics.drawable;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.DrawableContainer;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An internal DrawableContainer class, used to draw different things depending on animation scale.
|
||||
* i.e: animation scale can be 0 in battery saver mode.
|
||||
* This class contains 2 drawable, one is animatable, the other is static. When animation scale is
|
||||
* not 0, the animatable drawable will the drawn. Otherwise, the static drawable will be drawn.
|
||||
* <p>This class implements Animatable since ProgressBar can pick this up similarly as an
|
||||
* AnimatedVectorDrawable.
|
||||
* <p>It can be defined in an XML file with the {@code <AnimationScaleListDrawable>}
|
||||
* element.
|
||||
*/
|
||||
public class AnimationScaleListDrawable extends DrawableContainer implements Animatable {
|
||||
private static final String TAG = "AnimationScaleListDrawable";
|
||||
private AnimatedScaleListState mAnimatedScaleListState;
|
||||
private boolean mMutated;
|
||||
|
||||
public AnimationScaleListDrawable() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
private AnimationScaleListDrawable(@Nullable AnimatedScaleListState state,
|
||||
@Nullable Resources res) {
|
||||
// Every scale list drawable has its own constant state.
|
||||
final AnimatedScaleListState newState = new AnimatedScaleListState(state, this, res);
|
||||
setConstantState(newState);
|
||||
onStateChange(getState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current drawable according to the animation scale. If scale is 0, then pick the
|
||||
* static drawable, otherwise, pick the animatable drawable.
|
||||
*/
|
||||
@Override
|
||||
protected boolean onStateChange(int[] stateSet) {
|
||||
final boolean changed = super.onStateChange(stateSet);
|
||||
int idx = mAnimatedScaleListState.getCurrentDrawableIndexBasedOnScale();
|
||||
return selectDrawable(idx) || changed;
|
||||
}
|
||||
|
||||
|
||||
@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.AnimationScaleListDrawable);
|
||||
updateDensity(r);
|
||||
a.recycle();
|
||||
|
||||
inflateChildElements(r, parser, attrs, theme);
|
||||
|
||||
onStateChange(getState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Inflates child elements from XML.
|
||||
*/
|
||||
private void inflateChildElements(@NonNull Resources r, @NonNull XmlPullParser parser,
|
||||
@NonNull AttributeSet attrs, @Nullable Theme theme)
|
||||
throws XmlPullParserException, IOException {
|
||||
final AnimatedScaleListState state = mAnimatedScaleListState;
|
||||
final int innerDepth = parser.getDepth() + 1;
|
||||
int type;
|
||||
int depth;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& ((depth = parser.getDepth()) >= innerDepth
|
||||
|| type != XmlPullParser.END_TAG)) {
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (depth > innerDepth || !parser.getName().equals("item")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Either pick up the android:drawable attribute.
|
||||
final TypedArray a = obtainAttributes(r, theme, attrs,
|
||||
R.styleable.AnimationScaleListDrawableItem);
|
||||
Drawable dr = a.getDrawable(R.styleable.AnimationScaleListDrawableItem_drawable);
|
||||
a.recycle();
|
||||
|
||||
// Or parse the child element under <item>.
|
||||
if (dr == null) {
|
||||
while ((type = parser.next()) == XmlPullParser.TEXT) {
|
||||
}
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
throw new XmlPullParserException(
|
||||
parser.getPositionDescription()
|
||||
+ ": <item> tag requires a 'drawable' attribute or "
|
||||
+ "child tag defining a drawable");
|
||||
}
|
||||
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
|
||||
}
|
||||
|
||||
state.addDrawable(dr);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable mutate() {
|
||||
if (!mMutated && super.mutate() == this) {
|
||||
mAnimatedScaleListState.mutate();
|
||||
mMutated = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearMutated() {
|
||||
super.clearMutated();
|
||||
mMutated = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
Drawable dr = getCurrent();
|
||||
if (dr != null && dr instanceof Animatable) {
|
||||
((Animatable) dr).start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
Drawable dr = getCurrent();
|
||||
if (dr != null && dr instanceof Animatable) {
|
||||
((Animatable) dr).stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
boolean result = false;
|
||||
Drawable dr = getCurrent();
|
||||
if (dr != null && dr instanceof Animatable) {
|
||||
result = ((Animatable) dr).isRunning();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static class AnimatedScaleListState extends DrawableContainerState {
|
||||
int[] mThemeAttrs = null;
|
||||
// The index of the last static drawable.
|
||||
int mStaticDrawableIndex = -1;
|
||||
// The index of the last animatable drawable.
|
||||
int mAnimatableDrawableIndex = -1;
|
||||
|
||||
AnimatedScaleListState(AnimatedScaleListState orig, AnimationScaleListDrawable owner,
|
||||
Resources res) {
|
||||
super(orig, owner, res);
|
||||
|
||||
if (orig != null) {
|
||||
// Perform a shallow copy and rely on mutate() to deep-copy.
|
||||
mThemeAttrs = orig.mThemeAttrs;
|
||||
|
||||
mStaticDrawableIndex = orig.mStaticDrawableIndex;
|
||||
mAnimatableDrawableIndex = orig.mAnimatableDrawableIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mutate() {
|
||||
mThemeAttrs = mThemeAttrs != null ? mThemeAttrs.clone() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the drawable into the container.
|
||||
* This class only keep track one animatable drawable, and one static. If there are multiple
|
||||
* defined in the XML, then pick the last one.
|
||||
*/
|
||||
int addDrawable(Drawable drawable) {
|
||||
final int pos = addChild(drawable);
|
||||
if (drawable instanceof Animatable) {
|
||||
mAnimatableDrawableIndex = pos;
|
||||
} else {
|
||||
mStaticDrawableIndex = pos;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable() {
|
||||
return new AnimationScaleListDrawable(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable(Resources res) {
|
||||
return new AnimationScaleListDrawable(this, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canApplyTheme() {
|
||||
return mThemeAttrs != null || super.canApplyTheme();
|
||||
}
|
||||
|
||||
public int getCurrentDrawableIndexBasedOnScale() {
|
||||
if (ValueAnimator.getDurationScale() == 0) {
|
||||
return mStaticDrawableIndex;
|
||||
}
|
||||
return mAnimatableDrawableIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTheme(@NonNull Theme theme) {
|
||||
super.applyTheme(theme);
|
||||
|
||||
onStateChange(getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setConstantState(@NonNull DrawableContainerState state) {
|
||||
super.setConstantState(state);
|
||||
|
||||
if (state instanceof AnimatedScaleListState) {
|
||||
mAnimatedScaleListState = (AnimatedScaleListState) state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,4 @@ Copyright (C) 2016 The Android Open Source Project
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M17.65,6.35C16.2,4.9 14.21,4.0 12.0,4.0c-4.42,0.0 -7.99,3.58 -7.99,8.0s3.57,8.0 7.99,8.0c3.73,0.0 6.84,-2.55 7.73,-6.0l-2.08,0.0c-0.82,2.33 -3.04,4.0 -5.65,4.0 -3.31,0.0 -6.0,-2.69 -6.0,-6.0s2.69,-6.0 6.0,-6.0c1.66,0.0 3.1,0.69 4.22,1.78L13.0,11.0l7.0,0.0L20.0,4.0l-2.35,2.35z"/>
|
||||
<path
|
||||
android:pathData="M0 0h24v24H0z"
|
||||
android:fillColor="#00000000"/>
|
||||
</vector>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2016 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.
|
||||
-->
|
||||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/vector_drawable_progress_bar_large" >
|
||||
<target
|
||||
android:name="progressBar"
|
||||
android:animation="@anim/progress_indeterminate_material" />
|
||||
|
||||
<target
|
||||
android:name="root"
|
||||
android:animation="@anim/progress_indeterminate_rotation_material" />
|
||||
</animated-vector>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2016 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.
|
||||
-->
|
||||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/vector_drawable_progress_bar_medium" >
|
||||
|
||||
<target
|
||||
android:name="progressBar"
|
||||
android:animation="@anim/progress_indeterminate_material" />
|
||||
|
||||
<target
|
||||
android:name="root"
|
||||
android:animation="@anim/progress_indeterminate_rotation_material" />
|
||||
|
||||
</animated-vector>
|
||||
@@ -13,16 +13,8 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/vector_drawable_progress_bar_large" >
|
||||
|
||||
<target
|
||||
android:name="progressBar"
|
||||
android:animation="@anim/progress_indeterminate_material" />
|
||||
|
||||
<target
|
||||
android:name="root"
|
||||
android:animation="@anim/progress_indeterminate_rotation_material" />
|
||||
|
||||
</animated-vector>
|
||||
<com.android.internal.graphics.drawable.AnimationScaleListDrawable
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/progress_static_material" />
|
||||
<item android:drawable="@drawable/progress_indeterminate_anim_large_material" />
|
||||
</com.android.internal.graphics.drawable.AnimationScaleListDrawable>
|
||||
|
||||
@@ -13,15 +13,8 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/vector_drawable_progress_bar_medium" >
|
||||
|
||||
<target
|
||||
android:name="progressBar"
|
||||
android:animation="@anim/progress_indeterminate_material" />
|
||||
|
||||
<target
|
||||
android:name="root"
|
||||
android:animation="@anim/progress_indeterminate_rotation_material" />
|
||||
|
||||
</animated-vector>
|
||||
<com.android.internal.graphics.drawable.AnimationScaleListDrawable
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/progress_static_material" />
|
||||
<item android:drawable="@drawable/progress_indeterminate_anim_medium_material" />
|
||||
</com.android.internal.graphics.drawable.AnimationScaleListDrawable>
|
||||
|
||||
@@ -13,16 +13,17 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/vector_drawable_progress_bar_small" >
|
||||
|
||||
<target
|
||||
android:name="progressBar"
|
||||
android:animation="@anim/progress_indeterminate_material" />
|
||||
|
||||
<target
|
||||
android:name="root"
|
||||
android:animation="@anim/progress_indeterminate_rotation_material" />
|
||||
|
||||
</animated-vector>
|
||||
<com.android.internal.graphics.drawable.AnimationScaleListDrawable
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/progress_static_material" />
|
||||
<item>
|
||||
<animated-vector android:drawable="@drawable/vector_drawable_progress_bar_small" >
|
||||
<target
|
||||
android:name="progressBar"
|
||||
android:animation="@anim/progress_indeterminate_material" />
|
||||
<target
|
||||
android:name="root"
|
||||
android:animation="@anim/progress_indeterminate_rotation_material" />
|
||||
</animated-vector>
|
||||
</item>
|
||||
</com.android.internal.graphics.drawable.AnimationScaleListDrawable>
|
||||
|
||||
25
core/res/res/drawable/progress_static_material.xml
Normal file
25
core/res/res/drawable/progress_static_material.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2016 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
>
|
||||
<path
|
||||
android:fillColor="?attr/colorControlActivated"
|
||||
android:pathData="M17.65,6.35C16.2,4.9 14.21,4.0 12.0,4.0c-4.42,0.0 -7.99,3.58 -7.99,8.0s3.57,8.0 7.99,8.0c3.73,0.0 6.84,-2.55 7.73,-6.0l-2.08,0.0c-0.82,2.33 -3.04,4.0 -5.65,4.0 -3.31,0.0 -6.0,-2.69 -6.0,-6.0s2.69,-6.0 6.0,-6.0c1.66,0.0 3.1,0.69 4.22,1.78L13.0,11.0l7.0,0.0L20.0,4.0l-2.35,2.35z"/>
|
||||
</vector>
|
||||
@@ -5312,6 +5312,21 @@ i
|
||||
<attr name="alpha" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Drawable used to render according to the animation scale. Esp. when it is 0 due to battery
|
||||
saver mode. It should contain one animatable drawable and one static drawable.
|
||||
@hide -->
|
||||
<declare-styleable name="AnimationScaleListDrawable">
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Attributes that can be assigned to a AnimationScaleListDrawable item.
|
||||
@hide -->
|
||||
<declare-styleable name="AnimationScaleListDrawableItem">
|
||||
<!-- Reference to a drawable resource to use for the state. If not
|
||||
given, the drawable must be defined by the first child tag. -->
|
||||
<attr name="drawable" />
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<!-- Drawable used to render a geometric shape, with a gradient or a solid color. -->
|
||||
<declare-styleable name="GradientDrawable">
|
||||
<!-- Indicates whether the drawable should intially be visible. -->
|
||||
|
||||
@@ -1422,9 +1422,10 @@ public abstract class Drawable {
|
||||
/**
|
||||
* Obtains styled attributes from the theme, if available, or unstyled
|
||||
* resources if the theme is null.
|
||||
* @hide
|
||||
*/
|
||||
static @NonNull TypedArray obtainAttributes(@NonNull Resources res, @Nullable Theme theme,
|
||||
@NonNull AttributeSet set, @NonNull int[] attrs) {
|
||||
protected static @NonNull TypedArray obtainAttributes(@NonNull Resources res,
|
||||
@Nullable Theme theme, @NonNull AttributeSet set, @NonNull int[] attrs) {
|
||||
if (theme == null) {
|
||||
return res.obtainAttributes(set, attrs);
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ import android.graphics.ColorFilter;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.Rect;
|
||||
import android.os.SystemClock;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.LayoutDirection;
|
||||
@@ -601,8 +601,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
|
||||
* during inflation.
|
||||
*
|
||||
* @param res the resources used to inflate density-dependent values
|
||||
* @hide
|
||||
*/
|
||||
final void updateDensity(Resources res) {
|
||||
protected final void updateDensity(Resources res) {
|
||||
mDrawableContainerState.updateDensity(res);
|
||||
}
|
||||
|
||||
@@ -711,7 +712,10 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
|
||||
boolean mHasTintList;
|
||||
boolean mHasTintMode;
|
||||
|
||||
DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
protected DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
|
||||
Resources res) {
|
||||
mOwner = owner;
|
||||
mSourceRes = res != null ? res : (orig != null ? orig.mSourceRes : null);
|
||||
|
||||
Reference in New Issue
Block a user