Loading api/current.txt +45 −0 Original line number Diff line number Diff line Loading @@ -825,6 +825,7 @@ package android { field public static final int maxRows = 16843059; // 0x1010133 field public static final int maxSdkVersion = 16843377; // 0x1010271 field public static final int maxWidth = 16843039; // 0x101011f field public static final int maximumAngle = 16843905; // 0x1010481 field public static final int measureAllChildren = 16843018; // 0x101010a field public static final int measureWithLargestChild = 16843476; // 0x10102d4 field public static final int mediaRouteButtonStyle = 16843693; // 0x10103ad Loading @@ -840,6 +841,8 @@ package android { field public static final int minResizeWidth = 16843669; // 0x1010395 field public static final int minSdkVersion = 16843276; // 0x101020c field public static final int minWidth = 16843071; // 0x101013f field public static final int minimumHorizontalAngle = 16843903; // 0x101047f field public static final int minimumVerticalAngle = 16843904; // 0x1010480 field public static final int mipMap = 16843725; // 0x10103cd field public static final int mirrorForRtl = 16843726; // 0x10103ce field public static final int mode = 16843134; // 0x101017e Loading Loading @@ -30450,12 +30453,26 @@ package android.text.util { package android.transition { public class ArcMotion extends android.transition.PathMotion { ctor public ArcMotion(); ctor public ArcMotion(android.content.Context, android.util.AttributeSet); method public float getMaximumAngle(); method public float getMinimumHorizontalAngle(); method public float getMinimumVerticalAngle(); method public android.graphics.Path getPath(float, float, float, float); method public void setMaximumAngle(float); method public void setMinimumHorizontalAngle(float); method public void setMinimumVerticalAngle(float); } public class AutoTransition extends android.transition.TransitionSet { ctor public AutoTransition(); ctor public AutoTransition(android.content.Context, android.util.AttributeSet); } public class ChangeBounds extends android.transition.Transition { ctor public ChangeBounds(); ctor public ChangeBounds(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); method public void setReparent(boolean); Loading @@ -30464,18 +30481,21 @@ package android.transition { public class ChangeClipBounds extends android.transition.Transition { ctor public ChangeClipBounds(); ctor public ChangeClipBounds(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); } public class ChangeImageTransform extends android.transition.Transition { ctor public ChangeImageTransform(); ctor public ChangeImageTransform(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); } public class ChangeTransform extends android.transition.Transition { ctor public ChangeTransform(); ctor public ChangeTransform(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); } Loading @@ -30488,15 +30508,32 @@ package android.transition { public class Explode extends android.transition.Visibility { ctor public Explode(); ctor public Explode(android.content.Context, android.util.AttributeSet); } public class Fade extends android.transition.Visibility { ctor public Fade(); ctor public Fade(int); ctor public Fade(android.content.Context, android.util.AttributeSet); field public static final int IN = 1; // 0x1 field public static final int OUT = 2; // 0x2 } public abstract class PathMotion { ctor public PathMotion(); ctor public PathMotion(android.content.Context, android.util.AttributeSet); method public abstract android.graphics.Path getPath(float, float, float, float); } public class PatternMotion extends android.transition.PathMotion { ctor public PatternMotion(); ctor public PatternMotion(android.content.Context, android.util.AttributeSet); ctor public PatternMotion(android.graphics.Path); method public android.graphics.Path getPath(float, float, float, float); method public android.graphics.Path getPattern(); method public void setPattern(android.graphics.Path); } public final class Scene { ctor public Scene(android.view.ViewGroup); ctor public Scene(android.view.ViewGroup, android.view.View); Loading @@ -30519,11 +30556,14 @@ package android.transition { public class Slide extends android.transition.Visibility { ctor public Slide(); ctor public Slide(int); ctor public Slide(android.content.Context, android.util.AttributeSet); method public int getSlideEdge(); method public void setSlideEdge(int); } public abstract class Transition implements java.lang.Cloneable { ctor public Transition(); ctor public Transition(android.content.Context, android.util.AttributeSet); method public android.transition.Transition addListener(android.transition.Transition.TransitionListener); method public android.transition.Transition addTarget(int); method public android.transition.Transition addTarget(java.lang.String); Loading @@ -30546,6 +30586,7 @@ package android.transition { method public android.transition.Transition.EpicenterCallback getEpicenterCallback(); method public android.animation.TimeInterpolator getInterpolator(); method public java.lang.String getName(); method public android.transition.PathMotion getPathMotion(); method public android.transition.TransitionPropagation getPropagation(); method public long getStartDelay(); method public java.util.List<java.lang.Integer> getTargetIds(); Loading @@ -30563,6 +30604,7 @@ package android.transition { method public void setEpicenterCallback(android.transition.Transition.EpicenterCallback); method public android.transition.Transition setInterpolator(android.animation.TimeInterpolator); method public void setMatchOrder(int...); method public void setPathMotion(android.transition.PathMotion); method public void setPropagation(android.transition.TransitionPropagation); method public android.transition.Transition setStartDelay(long); field public static final int MATCH_ID = 3; // 0x3 Loading Loading @@ -30610,6 +30652,7 @@ package android.transition { public class TransitionSet extends android.transition.Transition { ctor public TransitionSet(); ctor public TransitionSet(android.content.Context, android.util.AttributeSet); method public android.transition.TransitionSet addTransition(android.transition.Transition); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); Loading @@ -30628,8 +30671,10 @@ package android.transition { public abstract class Visibility extends android.transition.Transition { ctor public Visibility(); ctor public Visibility(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); method public int getMode(); method public boolean isVisible(android.transition.TransitionValues); method public android.animation.Animator onAppear(android.view.ViewGroup, android.transition.TransitionValues, int, android.transition.TransitionValues, int); method public android.animation.Animator onAppear(android.view.ViewGroup, android.view.View, android.transition.TransitionValues, android.transition.TransitionValues); core/java/android/transition/ArcMotion.java 0 → 100644 +272 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 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.transition; import com.android.internal.R; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Path; import android.util.AttributeSet; import android.util.FloatMath; /** * A PathMotion that generates a curved path along an arc on an imaginary circle containing * the two points. If the horizontal distance between the points is less than the vertical * distance, then the circle's center point will be horizontally aligned with the end point. If the * vertical distance is less than the horizontal distance then the circle's center point * will be vertically aligned with the end point. * <p> * When the two points are near horizontal or vertical, the curve of the motion will be * small as the center of the circle will be far from both points. To force curvature of * the path, {@link #setMinimumHorizontalAngle(float)} and * {@link #setMinimumVerticalAngle(float)} may be used to set the minimum angle of the * arc between two points. * </p> * <p>This may be used in XML as an element inside a transition.</p> * <pre> * {@code * <changeBounds> * <arcMotion android:minimumHorizontalAngle="15" * android:minimumVerticalAngle="0" android:maximumAngle="90"/> * </changeBounds> * } * </pre> */ public class ArcMotion extends PathMotion { private static final float DEFAULT_MIN_ANGLE_DEGREES = 0; private static final float DEFAULT_MAX_ANGLE_DEGREES = 70; private static final float DEFAULT_MAX_TANGENT = (float) Math.tan(Math.toRadians(DEFAULT_MAX_ANGLE_DEGREES/2)); private float mMinimumHorizontalAngle = 0; private float mMinimumVerticalAngle = 0; private float mMaximumAngle = DEFAULT_MAX_ANGLE_DEGREES; private float mMinimumHorizontalTangent = 0; private float mMinimumVerticalTangent = 0; private float mMaximumTangent = DEFAULT_MAX_TANGENT; public ArcMotion() {} public ArcMotion(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ArcMotion); float minimumVerticalAngle = a.getFloat(R.styleable.ArcMotion_minimumVerticalAngle, DEFAULT_MIN_ANGLE_DEGREES); setMinimumVerticalAngle(minimumVerticalAngle); float minimumHorizontalAngle = a.getFloat(R.styleable.ArcMotion_minimumHorizontalAngle, DEFAULT_MIN_ANGLE_DEGREES); setMinimumHorizontalAngle(minimumHorizontalAngle); float maximumAngle = a.getFloat(R.styleable.ArcMotion_maximumAngle, DEFAULT_MAX_ANGLE_DEGREES); setMaximumAngle(maximumAngle); a.recycle(); } /** * Sets the minimum arc along the circle between two points aligned near horizontally. * When start and end points are close to horizontal, the calculated center point of the * circle will be far from both points, giving a near straight path between the points. * By setting a minimum angle, this forces the center point to be closer and give an * exaggerated curve to the path. * <p>The default value is 0.</p> * * @param angleInDegrees The minimum angle of the arc on a circle describing the Path * between two nearly horizontally-separated points. * @attr ref android.R.styleable#ArcMotion_minimumHorizontalAngle */ public void setMinimumHorizontalAngle(float angleInDegrees) { mMinimumHorizontalAngle = angleInDegrees; mMinimumHorizontalTangent = toTangent(angleInDegrees); } /** * Returns the minimum arc along the circle between two points aligned near horizontally. * When start and end points are close to horizontal, the calculated center point of the * circle will be far from both points, giving a near straight path between the points. * By setting a minimum angle, this forces the center point to be closer and give an * exaggerated curve to the path. * <p>The default value is 0.</p> * * @return The minimum arc along the circle between two points aligned near horizontally. * @attr ref android.R.styleable#ArcMotion_minimumHorizontalAngle */ public float getMinimumHorizontalAngle() { return mMinimumHorizontalAngle; } /** * Sets the minimum arc along the circle between two points aligned near vertically. * When start and end points are close to vertical, the calculated center point of the * circle will be far from both points, giving a near straight path between the points. * By setting a minimum angle, this forces the center point to be closer and give an * exaggerated curve to the path. * <p>The default value is 0.</p> * * @param angleInDegrees The minimum angle of the arc on a circle describing the Path * between two nearly vertically-separated points. * @attr ref android.R.styleable#ArcMotion_minimumVerticalAngle */ public void setMinimumVerticalAngle(float angleInDegrees) { mMinimumVerticalAngle = angleInDegrees; mMinimumVerticalTangent = toTangent(angleInDegrees); } /** * Returns the minimum arc along the circle between two points aligned near vertically. * When start and end points are close to vertical, the calculated center point of the * circle will be far from both points, giving a near straight path between the points. * By setting a minimum angle, this forces the center point to be closer and give an * exaggerated curve to the path. * <p>The default value is 0.</p> * * @return The minimum angle of the arc on a circle describing the Path * between two nearly vertically-separated points. * @attr ref android.R.styleable#ArcMotion_minimumVerticalAngle */ public float getMinimumVerticalAngle() { return mMinimumVerticalAngle; } /** * Sets the maximum arc along the circle between two points. When start and end points * have close to equal x and y differences, the curve between them is large. This forces * the curved path to have an arc of at most the given angle. * <p>The default value is 70 degrees.</p> * * @param angleInDegrees The maximum angle of the arc on a circle describing the Path * between the start and end points. * @attr ref android.R.styleable#ArcMotion_maximumAngle */ public void setMaximumAngle(float angleInDegrees) { mMaximumAngle = angleInDegrees; mMaximumTangent = toTangent(angleInDegrees); } /** * Returns the maximum arc along the circle between two points. When start and end points * have close to equal x and y differences, the curve between them is large. This forces * the curved path to have an arc of at most the given angle. * <p>The default value is 70 degrees.</p> * * @return The maximum angle of the arc on a circle describing the Path * between the start and end points. * @attr ref android.R.styleable#ArcMotion_maximumAngle */ public float getMaximumAngle() { return mMaximumAngle; } private static float toTangent(float arcInDegrees) { if (arcInDegrees < 0 || arcInDegrees > 90) { throw new IllegalArgumentException("Arc must be between 0 and 90 degrees"); } return (float) Math.tan(Math.toRadians(arcInDegrees / 2)); } @Override public Path getPath(float startX, float startY, float endX, float endY) { // Here's a little ascii art to show how this is calculated: // c---------- b // \ / | // \ d | // \ / e // a----f // This diagram assumes that the horizontal distance is less than the vertical // distance between The start point (a) and end point (b). // d is the midpoint between a and b. c is the center point of the circle with // This path is formed by assuming that start and end points are in // an arc on a circle. The end point is centered in the circle vertically // and start is a point on the circle. // Triangles bfa and bde form similar right triangles. The control points // for the cubic Bezier arc path are the midpoints between a and e and e and b. Path path = new Path(); path.moveTo(startX, startY); float ex; float ey; if (startY == endY) { ex = (startX + endX) / 2; ey = startY + mMinimumHorizontalTangent * Math.abs(endX - startX) / 2; } else if (startX == endX) { ex = startX + mMinimumVerticalTangent * Math.abs(endY - startY) / 2; ey = (startY + endY) / 2; } else { float deltaX = endX - startX; float deltaY = startY - endY; // Y is inverted compared to diagram above. // hypotenuse squared. float h2 = deltaX * deltaX + deltaY * deltaY; // Midpoint between start and end float dx = (startX + endX) / 2; float dy = (startY + endY) / 2; // Distance squared between end point and mid point is (1/2 hypotenuse)^2 float midDist2 = h2 * 0.25f; float minimumArcDist2 = 0; if (Math.abs(deltaX) < Math.abs(deltaY)) { // Similar triangles bfa and bde mean that (ab/fb = eb/bd) // Therefore, eb = ab * bd / fb // ab = hypotenuse // bd = hypotenuse/2 // fb = deltaY float eDistY = h2 / (2 * deltaY); ey = endY + eDistY; ex = endX; minimumArcDist2 = midDist2 * mMinimumVerticalTangent * mMinimumVerticalTangent; } else { // Same as above, but flip X & Y float eDistX = h2 / (2 * deltaX); ex = endX + eDistX; ey = endY; minimumArcDist2 = midDist2 * mMinimumHorizontalTangent * mMinimumHorizontalTangent; } float arcDistX = dx - ex; float arcDistY = dy - ey; float arcDist2 = arcDistX * arcDistX + arcDistY * arcDistY; float maximumArcDist2 = midDist2 * mMaximumTangent * mMaximumTangent; float newArcDistance2 = 0; if (arcDist2 < minimumArcDist2) { newArcDistance2 = minimumArcDist2; } else if (arcDist2 > maximumArcDist2) { newArcDistance2 = maximumArcDist2; } if (newArcDistance2 != 0) { float ratio2 = newArcDistance2 / arcDist2; float ratio = FloatMath.sqrt(ratio2); ex = dx + (ratio * (ex - dx)); ey = dy + (ratio * (ey - dy)); } } float controlX1 = (startX + ex) / 2; float controlY1 = (startY + ey) / 2; float controlX2 = (ex + endX) / 2; float controlY2 = (ey + endY) / 2; path.cubicTo(controlX1, controlY1, controlX2, controlY2, endX, endY); return path; } } core/java/android/transition/AutoTransition.java +12 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.transition; import android.content.Context; import android.util.AttributeSet; /** * Utility class for creating a default transition that automatically fades, * moves, and resizes views during a scene change. Loading @@ -33,6 +36,15 @@ public class AutoTransition extends TransitionSet { * */ public AutoTransition() { init(); } public AutoTransition(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setOrdering(ORDERING_SEQUENTIAL); addTransition(new Fade(Fade.OUT)). addTransition(new ChangeBounds()). Loading core/java/android/transition/ChangeBounds.java +73 −39 File changed.Preview size limit exceeded, changes collapsed. Show changes core/java/android/transition/ChangeClipBounds.java +8 −0 Original line number Diff line number Diff line Loading @@ -18,7 +18,9 @@ package android.transition; import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.RectEvaluator; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; Loading @@ -37,6 +39,12 @@ public class ChangeClipBounds extends Transition { PROPNAME_CLIP, }; public ChangeClipBounds() {} public ChangeClipBounds(Context context, AttributeSet attrs) { super(context, attrs); } @Override public String[] getTransitionProperties() { return sTransitionProperties; Loading Loading
api/current.txt +45 −0 Original line number Diff line number Diff line Loading @@ -825,6 +825,7 @@ package android { field public static final int maxRows = 16843059; // 0x1010133 field public static final int maxSdkVersion = 16843377; // 0x1010271 field public static final int maxWidth = 16843039; // 0x101011f field public static final int maximumAngle = 16843905; // 0x1010481 field public static final int measureAllChildren = 16843018; // 0x101010a field public static final int measureWithLargestChild = 16843476; // 0x10102d4 field public static final int mediaRouteButtonStyle = 16843693; // 0x10103ad Loading @@ -840,6 +841,8 @@ package android { field public static final int minResizeWidth = 16843669; // 0x1010395 field public static final int minSdkVersion = 16843276; // 0x101020c field public static final int minWidth = 16843071; // 0x101013f field public static final int minimumHorizontalAngle = 16843903; // 0x101047f field public static final int minimumVerticalAngle = 16843904; // 0x1010480 field public static final int mipMap = 16843725; // 0x10103cd field public static final int mirrorForRtl = 16843726; // 0x10103ce field public static final int mode = 16843134; // 0x101017e Loading Loading @@ -30450,12 +30453,26 @@ package android.text.util { package android.transition { public class ArcMotion extends android.transition.PathMotion { ctor public ArcMotion(); ctor public ArcMotion(android.content.Context, android.util.AttributeSet); method public float getMaximumAngle(); method public float getMinimumHorizontalAngle(); method public float getMinimumVerticalAngle(); method public android.graphics.Path getPath(float, float, float, float); method public void setMaximumAngle(float); method public void setMinimumHorizontalAngle(float); method public void setMinimumVerticalAngle(float); } public class AutoTransition extends android.transition.TransitionSet { ctor public AutoTransition(); ctor public AutoTransition(android.content.Context, android.util.AttributeSet); } public class ChangeBounds extends android.transition.Transition { ctor public ChangeBounds(); ctor public ChangeBounds(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); method public void setReparent(boolean); Loading @@ -30464,18 +30481,21 @@ package android.transition { public class ChangeClipBounds extends android.transition.Transition { ctor public ChangeClipBounds(); ctor public ChangeClipBounds(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); } public class ChangeImageTransform extends android.transition.Transition { ctor public ChangeImageTransform(); ctor public ChangeImageTransform(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); } public class ChangeTransform extends android.transition.Transition { ctor public ChangeTransform(); ctor public ChangeTransform(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); } Loading @@ -30488,15 +30508,32 @@ package android.transition { public class Explode extends android.transition.Visibility { ctor public Explode(); ctor public Explode(android.content.Context, android.util.AttributeSet); } public class Fade extends android.transition.Visibility { ctor public Fade(); ctor public Fade(int); ctor public Fade(android.content.Context, android.util.AttributeSet); field public static final int IN = 1; // 0x1 field public static final int OUT = 2; // 0x2 } public abstract class PathMotion { ctor public PathMotion(); ctor public PathMotion(android.content.Context, android.util.AttributeSet); method public abstract android.graphics.Path getPath(float, float, float, float); } public class PatternMotion extends android.transition.PathMotion { ctor public PatternMotion(); ctor public PatternMotion(android.content.Context, android.util.AttributeSet); ctor public PatternMotion(android.graphics.Path); method public android.graphics.Path getPath(float, float, float, float); method public android.graphics.Path getPattern(); method public void setPattern(android.graphics.Path); } public final class Scene { ctor public Scene(android.view.ViewGroup); ctor public Scene(android.view.ViewGroup, android.view.View); Loading @@ -30519,11 +30556,14 @@ package android.transition { public class Slide extends android.transition.Visibility { ctor public Slide(); ctor public Slide(int); ctor public Slide(android.content.Context, android.util.AttributeSet); method public int getSlideEdge(); method public void setSlideEdge(int); } public abstract class Transition implements java.lang.Cloneable { ctor public Transition(); ctor public Transition(android.content.Context, android.util.AttributeSet); method public android.transition.Transition addListener(android.transition.Transition.TransitionListener); method public android.transition.Transition addTarget(int); method public android.transition.Transition addTarget(java.lang.String); Loading @@ -30546,6 +30586,7 @@ package android.transition { method public android.transition.Transition.EpicenterCallback getEpicenterCallback(); method public android.animation.TimeInterpolator getInterpolator(); method public java.lang.String getName(); method public android.transition.PathMotion getPathMotion(); method public android.transition.TransitionPropagation getPropagation(); method public long getStartDelay(); method public java.util.List<java.lang.Integer> getTargetIds(); Loading @@ -30563,6 +30604,7 @@ package android.transition { method public void setEpicenterCallback(android.transition.Transition.EpicenterCallback); method public android.transition.Transition setInterpolator(android.animation.TimeInterpolator); method public void setMatchOrder(int...); method public void setPathMotion(android.transition.PathMotion); method public void setPropagation(android.transition.TransitionPropagation); method public android.transition.Transition setStartDelay(long); field public static final int MATCH_ID = 3; // 0x3 Loading Loading @@ -30610,6 +30652,7 @@ package android.transition { public class TransitionSet extends android.transition.Transition { ctor public TransitionSet(); ctor public TransitionSet(android.content.Context, android.util.AttributeSet); method public android.transition.TransitionSet addTransition(android.transition.Transition); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); Loading @@ -30628,8 +30671,10 @@ package android.transition { public abstract class Visibility extends android.transition.Transition { ctor public Visibility(); ctor public Visibility(android.content.Context, android.util.AttributeSet); method public void captureEndValues(android.transition.TransitionValues); method public void captureStartValues(android.transition.TransitionValues); method public int getMode(); method public boolean isVisible(android.transition.TransitionValues); method public android.animation.Animator onAppear(android.view.ViewGroup, android.transition.TransitionValues, int, android.transition.TransitionValues, int); method public android.animation.Animator onAppear(android.view.ViewGroup, android.view.View, android.transition.TransitionValues, android.transition.TransitionValues);
core/java/android/transition/ArcMotion.java 0 → 100644 +272 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 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.transition; import com.android.internal.R; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Path; import android.util.AttributeSet; import android.util.FloatMath; /** * A PathMotion that generates a curved path along an arc on an imaginary circle containing * the two points. If the horizontal distance between the points is less than the vertical * distance, then the circle's center point will be horizontally aligned with the end point. If the * vertical distance is less than the horizontal distance then the circle's center point * will be vertically aligned with the end point. * <p> * When the two points are near horizontal or vertical, the curve of the motion will be * small as the center of the circle will be far from both points. To force curvature of * the path, {@link #setMinimumHorizontalAngle(float)} and * {@link #setMinimumVerticalAngle(float)} may be used to set the minimum angle of the * arc between two points. * </p> * <p>This may be used in XML as an element inside a transition.</p> * <pre> * {@code * <changeBounds> * <arcMotion android:minimumHorizontalAngle="15" * android:minimumVerticalAngle="0" android:maximumAngle="90"/> * </changeBounds> * } * </pre> */ public class ArcMotion extends PathMotion { private static final float DEFAULT_MIN_ANGLE_DEGREES = 0; private static final float DEFAULT_MAX_ANGLE_DEGREES = 70; private static final float DEFAULT_MAX_TANGENT = (float) Math.tan(Math.toRadians(DEFAULT_MAX_ANGLE_DEGREES/2)); private float mMinimumHorizontalAngle = 0; private float mMinimumVerticalAngle = 0; private float mMaximumAngle = DEFAULT_MAX_ANGLE_DEGREES; private float mMinimumHorizontalTangent = 0; private float mMinimumVerticalTangent = 0; private float mMaximumTangent = DEFAULT_MAX_TANGENT; public ArcMotion() {} public ArcMotion(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ArcMotion); float minimumVerticalAngle = a.getFloat(R.styleable.ArcMotion_minimumVerticalAngle, DEFAULT_MIN_ANGLE_DEGREES); setMinimumVerticalAngle(minimumVerticalAngle); float minimumHorizontalAngle = a.getFloat(R.styleable.ArcMotion_minimumHorizontalAngle, DEFAULT_MIN_ANGLE_DEGREES); setMinimumHorizontalAngle(minimumHorizontalAngle); float maximumAngle = a.getFloat(R.styleable.ArcMotion_maximumAngle, DEFAULT_MAX_ANGLE_DEGREES); setMaximumAngle(maximumAngle); a.recycle(); } /** * Sets the minimum arc along the circle between two points aligned near horizontally. * When start and end points are close to horizontal, the calculated center point of the * circle will be far from both points, giving a near straight path between the points. * By setting a minimum angle, this forces the center point to be closer and give an * exaggerated curve to the path. * <p>The default value is 0.</p> * * @param angleInDegrees The minimum angle of the arc on a circle describing the Path * between two nearly horizontally-separated points. * @attr ref android.R.styleable#ArcMotion_minimumHorizontalAngle */ public void setMinimumHorizontalAngle(float angleInDegrees) { mMinimumHorizontalAngle = angleInDegrees; mMinimumHorizontalTangent = toTangent(angleInDegrees); } /** * Returns the minimum arc along the circle between two points aligned near horizontally. * When start and end points are close to horizontal, the calculated center point of the * circle will be far from both points, giving a near straight path between the points. * By setting a minimum angle, this forces the center point to be closer and give an * exaggerated curve to the path. * <p>The default value is 0.</p> * * @return The minimum arc along the circle between two points aligned near horizontally. * @attr ref android.R.styleable#ArcMotion_minimumHorizontalAngle */ public float getMinimumHorizontalAngle() { return mMinimumHorizontalAngle; } /** * Sets the minimum arc along the circle between two points aligned near vertically. * When start and end points are close to vertical, the calculated center point of the * circle will be far from both points, giving a near straight path between the points. * By setting a minimum angle, this forces the center point to be closer and give an * exaggerated curve to the path. * <p>The default value is 0.</p> * * @param angleInDegrees The minimum angle of the arc on a circle describing the Path * between two nearly vertically-separated points. * @attr ref android.R.styleable#ArcMotion_minimumVerticalAngle */ public void setMinimumVerticalAngle(float angleInDegrees) { mMinimumVerticalAngle = angleInDegrees; mMinimumVerticalTangent = toTangent(angleInDegrees); } /** * Returns the minimum arc along the circle between two points aligned near vertically. * When start and end points are close to vertical, the calculated center point of the * circle will be far from both points, giving a near straight path between the points. * By setting a minimum angle, this forces the center point to be closer and give an * exaggerated curve to the path. * <p>The default value is 0.</p> * * @return The minimum angle of the arc on a circle describing the Path * between two nearly vertically-separated points. * @attr ref android.R.styleable#ArcMotion_minimumVerticalAngle */ public float getMinimumVerticalAngle() { return mMinimumVerticalAngle; } /** * Sets the maximum arc along the circle between two points. When start and end points * have close to equal x and y differences, the curve between them is large. This forces * the curved path to have an arc of at most the given angle. * <p>The default value is 70 degrees.</p> * * @param angleInDegrees The maximum angle of the arc on a circle describing the Path * between the start and end points. * @attr ref android.R.styleable#ArcMotion_maximumAngle */ public void setMaximumAngle(float angleInDegrees) { mMaximumAngle = angleInDegrees; mMaximumTangent = toTangent(angleInDegrees); } /** * Returns the maximum arc along the circle between two points. When start and end points * have close to equal x and y differences, the curve between them is large. This forces * the curved path to have an arc of at most the given angle. * <p>The default value is 70 degrees.</p> * * @return The maximum angle of the arc on a circle describing the Path * between the start and end points. * @attr ref android.R.styleable#ArcMotion_maximumAngle */ public float getMaximumAngle() { return mMaximumAngle; } private static float toTangent(float arcInDegrees) { if (arcInDegrees < 0 || arcInDegrees > 90) { throw new IllegalArgumentException("Arc must be between 0 and 90 degrees"); } return (float) Math.tan(Math.toRadians(arcInDegrees / 2)); } @Override public Path getPath(float startX, float startY, float endX, float endY) { // Here's a little ascii art to show how this is calculated: // c---------- b // \ / | // \ d | // \ / e // a----f // This diagram assumes that the horizontal distance is less than the vertical // distance between The start point (a) and end point (b). // d is the midpoint between a and b. c is the center point of the circle with // This path is formed by assuming that start and end points are in // an arc on a circle. The end point is centered in the circle vertically // and start is a point on the circle. // Triangles bfa and bde form similar right triangles. The control points // for the cubic Bezier arc path are the midpoints between a and e and e and b. Path path = new Path(); path.moveTo(startX, startY); float ex; float ey; if (startY == endY) { ex = (startX + endX) / 2; ey = startY + mMinimumHorizontalTangent * Math.abs(endX - startX) / 2; } else if (startX == endX) { ex = startX + mMinimumVerticalTangent * Math.abs(endY - startY) / 2; ey = (startY + endY) / 2; } else { float deltaX = endX - startX; float deltaY = startY - endY; // Y is inverted compared to diagram above. // hypotenuse squared. float h2 = deltaX * deltaX + deltaY * deltaY; // Midpoint between start and end float dx = (startX + endX) / 2; float dy = (startY + endY) / 2; // Distance squared between end point and mid point is (1/2 hypotenuse)^2 float midDist2 = h2 * 0.25f; float minimumArcDist2 = 0; if (Math.abs(deltaX) < Math.abs(deltaY)) { // Similar triangles bfa and bde mean that (ab/fb = eb/bd) // Therefore, eb = ab * bd / fb // ab = hypotenuse // bd = hypotenuse/2 // fb = deltaY float eDistY = h2 / (2 * deltaY); ey = endY + eDistY; ex = endX; minimumArcDist2 = midDist2 * mMinimumVerticalTangent * mMinimumVerticalTangent; } else { // Same as above, but flip X & Y float eDistX = h2 / (2 * deltaX); ex = endX + eDistX; ey = endY; minimumArcDist2 = midDist2 * mMinimumHorizontalTangent * mMinimumHorizontalTangent; } float arcDistX = dx - ex; float arcDistY = dy - ey; float arcDist2 = arcDistX * arcDistX + arcDistY * arcDistY; float maximumArcDist2 = midDist2 * mMaximumTangent * mMaximumTangent; float newArcDistance2 = 0; if (arcDist2 < minimumArcDist2) { newArcDistance2 = minimumArcDist2; } else if (arcDist2 > maximumArcDist2) { newArcDistance2 = maximumArcDist2; } if (newArcDistance2 != 0) { float ratio2 = newArcDistance2 / arcDist2; float ratio = FloatMath.sqrt(ratio2); ex = dx + (ratio * (ex - dx)); ey = dy + (ratio * (ey - dy)); } } float controlX1 = (startX + ex) / 2; float controlY1 = (startY + ey) / 2; float controlX2 = (ex + endX) / 2; float controlY2 = (ey + endY) / 2; path.cubicTo(controlX1, controlY1, controlX2, controlY2, endX, endY); return path; } }
core/java/android/transition/AutoTransition.java +12 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.transition; import android.content.Context; import android.util.AttributeSet; /** * Utility class for creating a default transition that automatically fades, * moves, and resizes views during a scene change. Loading @@ -33,6 +36,15 @@ public class AutoTransition extends TransitionSet { * */ public AutoTransition() { init(); } public AutoTransition(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { setOrdering(ORDERING_SEQUENTIAL); addTransition(new Fade(Fade.OUT)). addTransition(new ChangeBounds()). Loading
core/java/android/transition/ChangeBounds.java +73 −39 File changed.Preview size limit exceeded, changes collapsed. Show changes
core/java/android/transition/ChangeClipBounds.java +8 −0 Original line number Diff line number Diff line Loading @@ -18,7 +18,9 @@ package android.transition; import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.RectEvaluator; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; Loading @@ -37,6 +39,12 @@ public class ChangeClipBounds extends Transition { PROPNAME_CLIP, }; public ChangeClipBounds() {} public ChangeClipBounds(Context context, AttributeSet attrs) { super(context, attrs); } @Override public String[] getTransitionProperties() { return sTransitionProperties; Loading