Skip to content

Instantly share code, notes, and snippets.

@guohai
Created April 3, 2012 16:55
  • Star 37 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save guohai/2293628 to your computer and use it in GitHub Desktop.
Curved Path Animation in Android
import android.graphics.PointF;
import android.view.animation.Animation;
import android.view.animation.Transformation;
// http://www.math.ubc.ca/~cass/gfx/bezier.html
public class ArcTranslateAnimation extends Animation {
private int mFromXType = ABSOLUTE;
private int mToXType = ABSOLUTE;
private int mFromYType = ABSOLUTE;
private int mToYType = ABSOLUTE;
private float mFromXValue = 0.0f;
private float mToXValue = 0.0f;
private float mFromYValue = 0.0f;
private float mToYValue = 0.0f;
private float mFromXDelta;
private float mToXDelta;
private float mFromYDelta;
private float mToYDelta;
private PointF mStart;
private PointF mControl;
private PointF mEnd;
/**
* Constructor to use when building a ArcTranslateAnimation from code
*
* @param fromXDelta
* Change in X coordinate to apply at the start of the animation
* @param toXDelta
* Change in X coordinate to apply at the end of the animation
* @param fromYDelta
* Change in Y coordinate to apply at the start of the animation
* @param toYDelta
* Change in Y coordinate to apply at the end of the animation
*/
public ArcTranslateAnimation(float fromXDelta, float toXDelta,
float fromYDelta, float toYDelta) {
mFromXValue = fromXDelta;
mToXValue = toXDelta;
mFromYValue = fromYDelta;
mToYValue = toYDelta;
mFromXType = ABSOLUTE;
mToXType = ABSOLUTE;
mFromYType = ABSOLUTE;
mToYType = ABSOLUTE;
}
/**
* Constructor to use when building a ArcTranslateAnimation from code
*
* @param fromXType
* Specifies how fromXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param fromXValue
* Change in X coordinate to apply at the start of the animation.
* This value can either be an absolute number if fromXType is
* ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param toXType
* Specifies how toXValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param toXValue
* Change in X coordinate to apply at the end of the animation.
* This value can either be an absolute number if toXType is
* ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param fromYType
* Specifies how fromYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param fromYValue
* Change in Y coordinate to apply at the start of the animation.
* This value can either be an absolute number if fromYType is
* ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
* @param toYType
* Specifies how toYValue should be interpreted. One of
* Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
* Animation.RELATIVE_TO_PARENT.
* @param toYValue
* Change in Y coordinate to apply at the end of the animation.
* This value can either be an absolute number if toYType is
* ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise.
*/
public ArcTranslateAnimation(int fromXType, float fromXValue, int toXType,
float toXValue, int fromYType, float fromYValue, int toYType,
float toYValue) {
mFromXValue = fromXValue;
mToXValue = toXValue;
mFromYValue = fromYValue;
mToYValue = toYValue;
mFromXType = fromXType;
mToXType = toXType;
mFromYType = fromYType;
mToYType = toYType;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float dx = calcBezier(interpolatedTime, mStart.x, mControl.x, mEnd.x);
float dy = calcBezier(interpolatedTime, mStart.y, mControl.y, mEnd.y);
t.getMatrix().setTranslate(dx, dy);
}
@Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mFromXDelta = resolveSize(mFromXType, mFromXValue, width, parentWidth);
mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth);
mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight);
mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight);
mStart = new PointF(mFromXDelta, mFromYDelta);
mEnd = new PointF(mToXDelta, mToYDelta);
mControl = new PointF(mFromXDelta, mToYDelta); // How to choose the
// Control point(we can
// use the cross of the
// two tangents from p0,
// p1)
}
/**
* Calculate the position on a quadratic bezier curve by given three points
* and the percentage of time passed.
*
* from http://en.wikipedia.org/wiki/B%C3%A9zier_curve
*
* @param interpolatedTime
* the fraction of the duration that has passed where 0 <= time
* <= 1
* @param p0
* a single dimension of the starting point
* @param p1
* a single dimension of the control point
* @param p2
* a single dimension of the ending point
*/
private long calcBezier(float interpolatedTime, float p0, float p1, float p2) {
return Math.round((Math.pow((1 - interpolatedTime), 2) * p0)
+ (2 * (1 - interpolatedTime) * interpolatedTime * p1)
+ (Math.pow(interpolatedTime, 2) * p2));
}
}
@sheharyarn
Copy link

Thankyou so much! I got it to work, I had misread the description of parameters. I was just supposed to use it like a simple TranslateAnimation:

ArcTranslateAnimation anim = new ArcTranslateAnimation(0, deltaX , 0, deltaY);
anim.setDuration(500);
anim.setFillAfter(true);

view.startAnimation(anim);

@newBlog
Copy link

newBlog commented May 6, 2015

ArcTranslateAnimation is working.
But you have to be requested.
because I do not speak English well.. so I will show you an image.
http://postfiles9.naver.net/20150507_200/luna000_1430941321114R55Ey_JPEG/arc_translate.jpg?type=w2
Could you please fix it

@rahulrj
Copy link

rahulrj commented Sep 18, 2015

HI. Can this class be used to move a view in a circular path or a circular arc of a circle.?
I am not getting it how to use it for the above use case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment