Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link

commented Jan 13, 2015

How do I use this? Can you please provide an example? Right now, I'm trying this but nothing happens:

int abs    = ArcTranslateAnimation.ABSOLUTE;

ArcTranslateAnimation arcAnim = new ArcTranslateAnimation(
    abs, startX, abs, finalX, abs, startY, abs, finalY
);

arcAnim.setDuration(3000);
arcAnim.setFillAfter(true);

myView.startAnimation(arcAnim);
@guohai

This comment has been minimized.

Copy link
Owner Author

commented Jan 13, 2015

Could you please show me more details, such as view type and device information under your test.

I have successfully run the demo(https://github.com/guohai/and-ui-bezier-demo) app on HTC D816(Android 4.4.2).
Or you can directly download the apk by https://drive.google.com/file/d/0Byif_EC71S3XNUV2RllJcFNnM00/view?usp=sharing

@sheharyarn

This comment has been minimized.

Copy link

commented Jan 14, 2015

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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
You can’t perform that action at this time.