diff options
author | George Mount <mount@google.com> | 2014-09-10 14:30:15 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-09-10 14:30:17 +0000 |
commit | b7d63aedf57e946c1a555e773d1e3591122544a7 (patch) | |
tree | c4629cc4a656f71381d083c7f18bba5a8eb5c374 | |
parent | cb0567f98cc6d13365a32c3adaa41078a8afc8d4 (diff) | |
parent | fd3c4744f265c5277e6e2641a18d5ec3dff19f6b (diff) | |
download | frameworks_base-b7d63aedf57e946c1a555e773d1e3591122544a7.zip frameworks_base-b7d63aedf57e946c1a555e773d1e3591122544a7.tar.gz frameworks_base-b7d63aedf57e946c1a555e773d1e3591122544a7.tar.bz2 |
Merge "Use intrinsic size for path animation in AnimatedVectorDrawable" into lmp-dev
4 files changed, 67 insertions, 22 deletions
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java index f4e4671..25417ed 100644 --- a/core/java/android/animation/AnimatorInflater.java +++ b/core/java/android/animation/AnimatorInflater.java @@ -92,21 +92,27 @@ public class AnimatorInflater { */ public static Animator loadAnimator(Resources resources, Theme theme, int id) throws NotFoundException { + return loadAnimator(resources, theme, id, 1); + } + + /** @hide */ + public static Animator loadAnimator(Resources resources, Theme theme, int id, + float pathErrorScale) throws NotFoundException { XmlResourceParser parser = null; try { parser = resources.getAnimation(id); - return createAnimatorFromXml(resources, theme, parser); + return createAnimatorFromXml(resources, theme, parser, pathErrorScale); } catch (XmlPullParserException ex) { Resources.NotFoundException rnf = new Resources.NotFoundException("Can't load animation resource ID #0x" + - Integer.toHexString(id)); + Integer.toHexString(id)); rnf.initCause(ex); throw rnf; } catch (IOException ex) { Resources.NotFoundException rnf = new Resources.NotFoundException("Can't load animation resource ID #0x" + - Integer.toHexString(id)); + Integer.toHexString(id)); rnf.initCause(ex); throw rnf; } finally { @@ -177,7 +183,7 @@ public class AnimatorInflater { } if (animator == null) { animator = createAnimatorFromXml(context.getResources(), - context.getTheme(), parser); + context.getTheme(), parser, 1f); } if (animator == null) { @@ -248,9 +254,11 @@ public class AnimatorInflater { * @param arrayAnimator Incoming typed array for Animator's attributes. * @param arrayObjectAnimator Incoming typed array for Object Animator's * attributes. + * @param pixelSize The relative pixel size, used to calculate the + * maximum error for path animations. */ private static void parseAnimatorFromTypeArray(ValueAnimator anim, - TypedArray arrayAnimator, TypedArray arrayObjectAnimator) { + TypedArray arrayAnimator, TypedArray arrayObjectAnimator, float pixelSize) { long duration = arrayAnimator.getInt(R.styleable.Animator_duration, 300); long startDelay = arrayAnimator.getInt(R.styleable.Animator_startOffset, 0); @@ -303,7 +311,7 @@ public class AnimatorInflater { } if (arrayObjectAnimator != null) { - setupObjectAnimator(anim, arrayObjectAnimator, getFloats); + setupObjectAnimator(anim, arrayObjectAnimator, getFloats, pixelSize); } } @@ -351,9 +359,11 @@ public class AnimatorInflater { * @param anim The target Animator which will be updated. * @param arrayObjectAnimator TypedArray for the ObjectAnimator. * @param getFloats True if the value type is float. + * @param pixelSize The relative pixel size, used to calculate the + * maximum error for path animations. */ private static void setupObjectAnimator(ValueAnimator anim, TypedArray arrayObjectAnimator, - boolean getFloats) { + boolean getFloats, float pixelSize) { ObjectAnimator oa = (ObjectAnimator) anim; String pathData = arrayObjectAnimator.getString(R.styleable.PropertyAnimator_pathData); @@ -370,7 +380,8 @@ public class AnimatorInflater { + " propertyXName or propertyYName is needed for PathData"); } else { Path path = PathParser.createPathFromPathData(pathData); - PathKeyframes keyframeSet = KeyframeSet.ofPath(path); + float error = 0.5f * pixelSize; // max half a pixel error + PathKeyframes keyframeSet = KeyframeSet.ofPath(path, error); Keyframes xKeyframes; Keyframes yKeyframes; if (getFloats) { @@ -487,13 +498,15 @@ public class AnimatorInflater { } } - private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser) + private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser, + float pixelSize) throws XmlPullParserException, IOException { - return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0); + return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0, + pixelSize); } private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser, - AttributeSet attrs, AnimatorSet parent, int sequenceOrdering) + AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize) throws XmlPullParserException, IOException { Animator anim = null; @@ -513,9 +526,9 @@ public class AnimatorInflater { String name = parser.getName(); if (name.equals("objectAnimator")) { - anim = loadObjectAnimator(res, theme, attrs); + anim = loadObjectAnimator(res, theme, attrs, pixelSize); } else if (name.equals("animator")) { - anim = loadAnimator(res, theme, attrs, null); + anim = loadAnimator(res, theme, attrs, null, pixelSize); } else if (name.equals("set")) { anim = new AnimatorSet(); TypedArray a; @@ -526,7 +539,8 @@ public class AnimatorInflater { } int ordering = a.getInt(R.styleable.AnimatorSet_ordering, TOGETHER); - createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering); + createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering, + pixelSize); a.recycle(); } else { throw new RuntimeException("Unknown animator name: " + parser.getName()); @@ -556,11 +570,11 @@ public class AnimatorInflater { } - private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs) - throws NotFoundException { + private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs, + float pathErrorScale) throws NotFoundException { ObjectAnimator anim = new ObjectAnimator(); - loadAnimator(res, theme, attrs, anim); + loadAnimator(res, theme, attrs, anim, pathErrorScale); return anim; } @@ -575,7 +589,7 @@ public class AnimatorInflater { * ObjectAnimator */ private static ValueAnimator loadAnimator(Resources res, Theme theme, - AttributeSet attrs, ValueAnimator anim) + AttributeSet attrs, ValueAnimator anim, float pathErrorScale) throws NotFoundException { TypedArray arrayAnimator = null; @@ -601,7 +615,7 @@ public class AnimatorInflater { anim = new ValueAnimator(); } - parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator); + parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator, pathErrorScale); final int resID = arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0); diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java index fc9bbb1..8d15db2 100644 --- a/core/java/android/animation/KeyframeSet.java +++ b/core/java/android/animation/KeyframeSet.java @@ -154,6 +154,10 @@ class KeyframeSet implements Keyframes { return new PathKeyframes(path); } + public static PathKeyframes ofPath(Path path, float error) { + return new PathKeyframes(path, error); + } + /** * Sets the TypeEvaluator to be used when calculating animated values. This object * is required only for KeyframeSets that are not either IntKeyframeSet or FloatKeyframeSet, diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index ba22550..e5e2f18 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -252,6 +252,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { throws XmlPullParserException, IOException { int eventType = parser.getEventType(); + float pathErrorScale = 1; while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { final String tagName = parser.getName(); @@ -261,9 +262,11 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { int drawableRes = a.getResourceId( R.styleable.AnimatedVectorDrawable_drawable, 0); if (drawableRes != 0) { - mAnimatedVectorState.mVectorDrawable = (VectorDrawable) res.getDrawable( + VectorDrawable vectorDrawable = (VectorDrawable) res.getDrawable( drawableRes, theme).mutate(); - mAnimatedVectorState.mVectorDrawable.setAllowCaching(false); + vectorDrawable.setAllowCaching(false); + pathErrorScale = vectorDrawable.getPixelSize(); + mAnimatedVectorState.mVectorDrawable = vectorDrawable; } a.recycle(); } else if (TARGET.equals(tagName)) { @@ -275,7 +278,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { int id = a.getResourceId( R.styleable.AnimatedVectorDrawableTarget_animation, 0); if (id != 0) { - Animator objectAnimator = AnimatorInflater.loadAnimator(res, theme, id); + Animator objectAnimator = AnimatorInflater.loadAnimator(res, theme, id, + pathErrorScale); setupAnimatorsForTarget(target, objectAnimator); } a.recycle(); diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index 042da5b..a07ccc4 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -368,6 +368,29 @@ public class VectorDrawable extends Drawable { } } + /** + * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension. + * This is used to calculate the path animation accuracy. + * + * @hide + */ + public float getPixelSize() { + if (mVectorState == null && mVectorState.mVPathRenderer == null || + mVectorState.mVPathRenderer.mBaseWidth == 0 || + mVectorState.mVPathRenderer.mBaseHeight == 0 || + mVectorState.mVPathRenderer.mViewportHeight == 0 || + mVectorState.mVPathRenderer.mViewportWidth == 0) { + return 1; // fall back to 1:1 pixel mapping. + } + float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth; + float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight; + float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth; + float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight; + float scaleX = viewportWidth / intrinsicWidth; + float scaleY = viewportHeight / intrinsicHeight; + return Math.min(scaleX, scaleY); + } + /** @hide */ public static VectorDrawable create(Resources resources, int rid) { try { |