Merge "Use real screen size to scale duration"

This commit is contained in:
Doris Liu
2015-04-17 23:40:47 +00:00
committed by Android (Google) Code Review
5 changed files with 78 additions and 30 deletions

View File

@@ -2880,7 +2880,7 @@ package android.animation {
method public void removePauseListener(android.animation.Animator.AnimatorPauseListener);
method public void resume();
method public abstract android.animation.Animator setDuration(long);
method public void setDurationScaleHint(int, android.content.res.Resources);
method public void setDurationScaleHint(android.content.Context, int);
method public abstract void setInterpolator(android.animation.TimeInterpolator);
method public abstract void setStartDelay(long);
method public void setTarget(java.lang.Object);

View File

@@ -2960,7 +2960,7 @@ package android.animation {
method public void removePauseListener(android.animation.Animator.AnimatorPauseListener);
method public void resume();
method public abstract android.animation.Animator setDuration(long);
method public void setDurationScaleHint(int, android.content.res.Resources);
method public void setDurationScaleHint(android.content.Context, int);
method public abstract void setInterpolator(android.animation.TimeInterpolator);
method public abstract void setStartDelay(long);
method public void setTarget(java.lang.Object);

View File

@@ -16,6 +16,7 @@
package android.animation;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.ConstantState;
import android.content.res.Resources;
@@ -37,7 +38,7 @@ public abstract class Animator implements Cloneable {
public static final int HINT_NO_SCALE = 0;
/**
* Set this scale hint (using {@link #setDurationScaleHint(int, Resources)} when the animation's
* Set this scale hint (using {@link #setDurationScaleHint(Context, int)} when the animation's
* moving distance is proportional to the screen size. (e.g. a view coming in from the bottom of
* the screen to top/center). With this scale hint set, the animation duration will be
* automatically scaled based on screen size.
@@ -45,7 +46,7 @@ public abstract class Animator implements Cloneable {
public static final int HINT_DISTANCE_PROPORTIONAL_TO_SCREEN_SIZE = 1;
/**
* Set this scale hint (using {@link #setDurationScaleHint(int, Resources)}) if the animation
* Set this scale hint (using {@link #setDurationScaleHint(Context, int)}) if the animation
* has pre-defined moving distance in dp that does not vary from device to device. This is
* extremely useful when the animation needs to run on both phones/tablets and TV, because TV
* has inflated dp and therefore will have a longer visual arc for the same animation than on
@@ -237,12 +238,27 @@ public abstract class Animator implements Cloneable {
* users' field of view. Therefore, the duration scale factor is determined by the ratio of the
* angular movement on current devices to that on the baseline device (i.e. Nexus 5).
*
* @param context Context used to determine the display metrics
* @param hint an indicator on how the animation is defined. The hint could be
* {@link #HINT_NO_SCALE}, {@link #HINT_DISTANCE_PROPORTIONAL_TO_SCREEN_SIZE} or
* {@link #HINT_DISTANCE_DEFINED_IN_DP}.
* @param res The resources {@see android.content.res.Resources} for getting display metrics
*/
public void setDurationScaleHint(int hint, Resources res) {
public void setDurationScaleHint(Context context, int hint) {
if (ANIM_DEBUG) {
Log.d("ANIM_DEBUG", "distance based duration hint: " + hint);
}
if (hint == mDurationScaleHint) {
return;
}
if (hint == HINT_NO_SCALE) {
mDurationScaleHint = hint;
return;
}
DisplayMetrics metrics = AnimationUtils.getRealDisplayMetrics(context);
setDurationScaleHint(context.getResources(), metrics, hint);
}
void setDurationScaleHint(Resources res, DisplayMetrics metrics, int hint) {
if (ANIM_DEBUG) {
Log.d("ANIM_DEBUG", "distance based duration hint: " + hint);
}
@@ -252,9 +268,9 @@ public abstract class Animator implements Cloneable {
mDurationScaleHint = hint;
if (hint != HINT_NO_SCALE) {
int uiMode = res.getConfiguration().uiMode & Configuration.UI_MODE_TYPE_MASK;
DisplayMetrics metrics = res.getDisplayMetrics();
float width = metrics.widthPixels / metrics.xdpi;
float height = metrics.heightPixels / metrics.ydpi;
float dpi = metrics.xdpi;
float width = metrics.widthPixels / dpi;
float height = metrics.heightPixels / dpi;
float viewingDistance = AnimationUtils.getViewingDistance(width, height, uiMode);
if (ANIM_DEBUG) {
Log.d("ANIM_DEBUG", "width, height, viewing distance, uimode: "
@@ -263,7 +279,7 @@ public abstract class Animator implements Cloneable {
mScreenSizeBasedDurationScale = AnimationUtils
.getScreenSizeBasedDurationScale(width, height, viewingDistance);
mDpBasedDurationScale = AnimationUtils.getDpBasedDurationScale(
metrics.density, metrics.xdpi, viewingDistance);
metrics.density, dpi, viewingDistance);
if (ANIM_DEBUG) {
Log.d("ANIM_DEBUG", "screen based scale, dp based scale: " +
mScreenSizeBasedDurationScale + ", " + mDpBasedDurationScale);

View File

@@ -26,6 +26,7 @@ import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.PathParser;
import android.util.StateSet;
@@ -85,34 +86,47 @@ public class AnimatorInflater {
/**
* Loads an {@link Animator} object from a resource
*
* @param context Application context used to access resources
* @param context Context used to access resources
* @param id The resource id of the animation to load
* @return The animator object reference by the specified id
* @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
*/
public static Animator loadAnimator(Context context, @AnimatorRes int id)
throws NotFoundException {
return loadAnimator(context.getResources(), context.getTheme(), id);
return loadAnimator(context, context.getTheme(), id);
}
/**
* Loads an {@link Animator} object from a resource
*
* @param resources The resources
* @param context Context used to access resources
* @param theme The theme
* @param id The resource id of the animation to load
* @return The animator object reference by the specified id
* @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
* @hide
*/
public static Animator loadAnimator(Resources resources, Theme theme, int id)
public static Animator loadAnimator(Context context, Theme theme, int id)
throws NotFoundException {
return loadAnimator(resources, theme, id, 1);
return loadAnimator(context, theme, id, 1);
}
/** @hide */
public static Animator loadAnimator(Resources resources, Theme theme, int id,
float pathErrorScale) throws NotFoundException {
DisplayMetrics metrics = resources.getDisplayMetrics();
return loadAnimator(resources, theme, id, pathErrorScale, metrics);
}
private static Animator loadAnimator(Context context, Theme theme, int id, float pathErrorScale)
throws NotFoundException {
DisplayMetrics metrics = AnimationUtils.getRealDisplayMetrics(context);
return loadAnimator(context.getResources(), theme, id, pathErrorScale, metrics);
}
private static Animator loadAnimator(Resources resources, Theme theme, int id,
float pathErrorScale, DisplayMetrics metrics) {
final ConfigurationBoundResourceCache<Animator> animatorCache = resources
.getAnimatorCache();
Animator animator = animatorCache.get(id, theme);
@@ -127,7 +141,7 @@ public class AnimatorInflater {
XmlResourceParser parser = null;
try {
parser = resources.getAnimation(id);
animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale);
animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale, metrics);
if (animator != null) {
animator.appendChangingConfigurations(getChangingConfigs(resources, id));
final ConstantState<Animator> constantState = animator.createConstantState();
@@ -239,7 +253,8 @@ public class AnimatorInflater {
}
if (animator == null) {
animator = createAnimatorFromXml(context.getResources(),
context.getTheme(), parser, 1f);
context.getTheme(), parser, 1f,
AnimationUtils.getRealDisplayMetrics(context));
}
if (animator == null) {
@@ -656,15 +671,15 @@ public class AnimatorInflater {
}
private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
float pixelSize)
float pixelSize, DisplayMetrics metrics)
throws XmlPullParserException, IOException {
return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0,
pixelSize);
pixelSize, metrics);
}
private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize)
throws XmlPullParserException, IOException {
AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize,
DisplayMetrics metrics) throws XmlPullParserException, IOException {
Animator anim = null;
ArrayList<Animator> childAnims = null;
@@ -683,9 +698,9 @@ public class AnimatorInflater {
boolean gotValues = false;
if (name.equals("objectAnimator")) {
anim = loadObjectAnimator(res, theme, attrs, pixelSize);
anim = loadObjectAnimator(res, theme, attrs, pixelSize, metrics);
} else if (name.equals("animator")) {
anim = loadAnimator(res, theme, attrs, null, pixelSize);
anim = loadAnimator(res, theme, attrs, null, pixelSize, metrics);
} else if (name.equals("set")) {
anim = new AnimatorSet();
TypedArray a;
@@ -697,10 +712,10 @@ public class AnimatorInflater {
anim.appendChangingConfigurations(a.getChangingConfigurations());
int ordering = a.getInt(R.styleable.AnimatorSet_ordering, TOGETHER);
createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering,
pixelSize);
pixelSize, metrics);
final int hint = a.getInt(R.styleable.AnimatorSet_durationScaleHint,
HINT_NO_SCALE);
anim.setDurationScaleHint(hint, res);
anim.setDurationScaleHint(res, metrics, hint);
a.recycle();
} else if (name.equals("propertyValuesHolder")) {
PropertyValuesHolder[] values = loadValues(res, theme, parser,
@@ -980,10 +995,10 @@ public class AnimatorInflater {
}
private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs,
float pathErrorScale) throws NotFoundException {
float pathErrorScale, DisplayMetrics metrics) throws NotFoundException {
ObjectAnimator anim = new ObjectAnimator();
loadAnimator(res, theme, attrs, anim, pathErrorScale);
loadAnimator(res, theme, attrs, anim, pathErrorScale, metrics);
return anim;
}
@@ -998,7 +1013,7 @@ public class AnimatorInflater {
* ObjectAnimator
*/
private static ValueAnimator loadAnimator(Resources res, Theme theme,
AttributeSet attrs, ValueAnimator anim, float pathErrorScale)
AttributeSet attrs, ValueAnimator anim, float pathErrorScale, DisplayMetrics metrics)
throws NotFoundException {
TypedArray arrayAnimator = null;
TypedArray arrayObjectAnimator = null;
@@ -1039,7 +1054,7 @@ public class AnimatorInflater {
final int hint = arrayAnimator.getInt(R.styleable.Animator_durationScaleHint,
HINT_NO_SCALE);
anim.setDurationScaleHint(hint, res);
anim.setDurationScaleHint(res, metrics, hint);
arrayAnimator.recycle();
if (arrayObjectAnimator != null) {
arrayObjectAnimator.recycle();

View File

@@ -16,7 +16,10 @@
package android.view.animation;
import android.app.Activity;
import android.content.res.Configuration;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -48,7 +51,7 @@ public class AnimationUtils {
private static final float RECOMMENDED_FIELD_OF_VIEW_FOR_TV = 40f;
private static final float ESTIMATED_VIEWING_DISTANCE_FOR_WATCH = 11f;
private static final float AVERAGE_VIEWING_DISTANCE_FOR_PHONES = 14.2f;
private static final float N5_DIAGONAL_VIEW_ANGLE = 19.58f;
private static final float N5_DIAGONAL_VIEW_ANGLE = 19.887228f;
private static final float N5_DENSITY = 3.0f;
private static final float N5_DPI = 443f;
@@ -452,4 +455,18 @@ public class AnimationUtils {
AVERAGE_VIEWING_DISTANCE_FOR_PHONES) * 2;
return anglePerDp / baselineAnglePerDp;
}
/**
* @hide
*/
public static DisplayMetrics getRealDisplayMetrics(Context context) {
DisplayMetrics metrics = new DisplayMetrics();
if (context instanceof Activity) {
((Activity) context).getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
} else {
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay()
.getRealMetrics(metrics);
}
return metrics;
}
}