Skip to content

Instantly share code, notes, and snippets.

@vaibhav-jani
Last active June 13, 2016 06:55
Show Gist options
  • Select an option

  • Save vaibhav-jani/680dd710c00dad9ba9ccd25a7c35758e to your computer and use it in GitHub Desktop.

Select an option

Save vaibhav-jani/680dd710c00dad9ba9ccd25a7c35758e to your computer and use it in GitHub Desktop.
Animation : Rotate view across another view
package ui.animation;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
public class CircularPropertyAnimation extends Animation {
private float startAngle = 90;
private View animatingView;
private View rotationAnchorView;
private float cx, cy; // center x,y position of circular path
private float prevX, prevY; // previous x,y position of image during animation
private float r; // radius of circle
private float prevDx, prevDy;
private int width;
private AnimationListener animationListener;
private OnTransformationListener onTransformationListener;
private boolean isRadiusConstant;
public OnTransformationListener getOnTransformationListener() {
return onTransformationListener;
}
public void setOnTransformationListener(OnTransformationListener onTransformationListener) {
this.onTransformationListener = onTransformationListener;
}
public AnimationListener getMyAnimationListener() {
return animationListener;
}
public void setMyAnimationListener(AnimationListener animationListener) {
this.animationListener = animationListener;
}
public interface OnTransformationListener {
public void onTransform(float dx, float dy);
}
/**
* @param rotationAnchorView - View that will be animated
* @param startAngle - startAngle
*/
public CircularPropertyAnimation(View animatingView, View rotationAnchorView, float startAngle) {
this.animatingView = animatingView;
this.rotationAnchorView = rotationAnchorView;
this.startAngle = startAngle;
}
@Override
public boolean willChangeBounds() {
return true;
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
this.width = width;
// calculate position of image center
/*int cxImage = width / 2;
int cyImage = height / 2;
cx = view.getLeft() + cxImage;
cy = view.getTop() + cyImage;*/
cx = rotationAnchorView.getWidth() / 2.0f;
cy = animatingView.getHeight() / 2.0f;
if (r == 0) {
r = cx;
}
// set previous position to center
prevX = cx;
prevY = cy;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation transformationX) {
if (interpolatedTime == 0) {
//t.getMatrix().setTranslate(prevDx, prevDy);
animatingView.setTranslationX(prevDx);
animatingView.setTranslationY(prevDy);
return;
}
float angleDeg = (interpolatedTime * 1800f + startAngle) % 1800f;
float angleRad = (float) Math.toRadians(angleDeg);
Log.d("CPA", "interpolatedTime : " + interpolatedTime);
Log.d("CPA", "angleDeg : " + angleDeg);
// r = radius, cx and cy = center point, a = angle (radians)
float x = (float) (cx + r * Math.cos(angleRad));
float y = (float) (cy + r * Math.sin(angleRad));
if (!isRadiusConstant) {
r = r - (r * interpolatedTime / 200.0f);
}
if (r < width / 2) {
r = width / 2;
}
float dx = prevX - x;
float dy = prevY - y;
prevX = x;
prevY = y;
prevDx = dx;
prevDy = dy;
//t.getMatrix().setTranslate(dx, dy);
animatingView.setTranslationX(dx);
animatingView.setTranslationY(dy);
if (onTransformationListener != null) {
onTransformationListener.onTransform(dx, dy);
}
}
public float getPrevDx() {
return prevDx;
}
public void setPrevDx(float prevDx) {
this.prevDx = prevDx;
}
public float getPrevDy() {
return prevDy;
}
public void setPrevDy(float prevDy) {
this.prevDy = prevDy;
}
public boolean isRadiusConstant() {
return isRadiusConstant;
}
public void setRadiusConstant(boolean radiusConstant) {
isRadiusConstant = radiusConstant;
}
}
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
/*
//Use case::
final CircularPropertyAnimation anim = new CircularPropertyAnimation(view, ivCircle, startAngle);
anim.setInterpolator(new LinearInterpolator());
anim.setDuration(18000);
anim.setRadiusConstant(true);
anim.setRepeatCount(200);
view.startAnimation(anim);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
view.setVisibility(View.VISIBLE);
}
}, 300);
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
view.setDrawingCacheEnabled(true);
}
@Override
public void onAnimationEnd(Animation animation) {
view.setDrawingCacheEnabled(false);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
anim.setTransitionListener(new CircularPropertyAnimation.TransitionListener() {
@Override
public void onAngleChange(float angle) {
view.setTag(angle);
}
});
*/
public class CircularPropertyAnimation extends Animation {
private float startAngle = 90;
private View animatingView;
private View rotationAnchorView;
private float cx, cy; // center x,y position of circular path
private float prevX, prevY; // previous x,y position of image during animation
private float r; // radius of quiz_match_circle
private float prevDx, prevDy;
private int width;
private float rotationCount = 2f;
private boolean isRadiusConstant = true;
private float totalAngle;
private TransitionListener transitionListener;
public TransitionListener getTransitionListener() {
return transitionListener;
}
public void setTransitionListener(TransitionListener transitionListener) {
this.transitionListener = transitionListener;
}
public interface TransitionListener {
public void onAngleChange(float angle);
}
/**
* @param rotationAnchorView - View that will be animated
* @param startAngle - startAngle
*/
public CircularPropertyAnimation(View animatingView, View rotationAnchorView, float startAngle) {
this.animatingView = animatingView;
this.rotationAnchorView = rotationAnchorView;
this.startAngle = startAngle;
}
public boolean isRadiusConstant() {
return isRadiusConstant;
}
public void setRadiusConstant(boolean radiusConstant) {
isRadiusConstant = radiusConstant;
}
@Override
public boolean willChangeBounds() {
return true;
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
this.width = width;
// calculate position of image center
/*int cxImage = width / 2;
int cyImage = height / 2;
cx = view.getLeft() + cxImage;
cy = view.getTop() + cyImage;*/
if (cx == 0) {
cx = rotationAnchorView.getWidth() / 2.0f;
}
if (cy == 0) {
cy = animatingView.getHeight() / 2.0f;
}
if (r == 0) {
r = cx;
}
// set previous position to center
prevX = cx;
prevY = cy;
if (totalAngle == 0) {
totalAngle = (360.0f * rotationCount);
}
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation transformationX) {
if (interpolatedTime == 0) {
//t.getMatrix().setTranslate(prevDx, prevDy);
//animatingView.setTranslationX(prevDx);
//animatingView.setTranslationY(prevDy);
return;
}
float angleDeg = (interpolatedTime * totalAngle + startAngle) % totalAngle;
float angleRad = (float) Math.toRadians(angleDeg);
//Log.d("CPA", "interpolatedTime : " + interpolatedTime);
//Log.d("CPA", "angleDeg : " + angleDeg);
// r = radius, cx and cy = center point, a = angle (radians)
float x = (float) (cx + r * Math.cos(angleRad));
float y = (float) (cy + r * Math.sin(angleRad));
if (!isRadiusConstant) {
r = r - (r * interpolatedTime / 200.0f);
}
//To meet in center
/*if (r < width / 2) {
r = width / 2;
}*/
//To stay apart
if (r < width) {
r = width;
}
float dx = prevX - x;
float dy = prevY - y;
prevX = x;
prevY = y;
prevDx = dx;
prevDy = dy;
//t.getMatrix().setTranslate(dx, dy);
animatingView.setTranslationX(dx);
animatingView.setTranslationY(dy);
if(transitionListener != null) {
transitionListener.onAngleChange(angleDeg);
}
}
public float getRotationCount() {
return rotationCount;
}
public void setRotationCount(float rotationCount) {
this.rotationCount = rotationCount;
totalAngle = rotationCount * 360.0f;
}
}
package ui.animation;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.RelativeLayout;
public class CircularViewAnimation extends Animation {
private float startAngle = 90;
private View animatingView;
private View rotationAnchorView;
private float cx, cy; // center x,y position of circular path
private float prevX, prevY; // previous x,y position of image during animation
private float r; // radius of circle
private float prevDx, prevDy;
private int width;
private AnimationListener animationListener;
private OnTransformationListener onTransformationListener;
private boolean isRadiusConstant;
public OnTransformationListener getOnTransformationListener() {
return onTransformationListener;
}
public void setOnTransformationListener(OnTransformationListener onTransformationListener) {
this.onTransformationListener = onTransformationListener;
}
public AnimationListener getMyAnimationListener() {
return animationListener;
}
public void setMyAnimationListener(AnimationListener animationListener) {
this.animationListener = animationListener;
}
public interface OnTransformationListener {
public void onTransform(float dx, float dy);
}
/**
* @param rotationAnchorView - View that will be animated
* @param startAngle - startAngle
*/
public CircularViewAnimation(View animatingView, View rotationAnchorView, float startAngle) {
this.animatingView = animatingView;
this.rotationAnchorView = rotationAnchorView;
this.startAngle = startAngle;
initThings();
}
private void initThings() {
setAnimationListener(mAnimationListener);
}
AnimationListener mAnimationListener = new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
if(animationListener != null) {
animationListener.onAnimationStart(animation);
}
}
@Override
public void onAnimationEnd(Animation animation) {
RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(animatingView.getWidth(), animatingView.getHeight());
params2.leftMargin += getPrevDx() + rotationAnchorView.getLeft() + rotationAnchorView.getWidth()/2 - animatingView.getWidth()/2;
params2.topMargin += getPrevDy() + rotationAnchorView.getTop() + rotationAnchorView.getHeight()/2 - animatingView.getHeight()/2;
Log.d("params2.leftMargin", ""+params2.leftMargin);
Log.d("params2.topMargin", ""+params2.topMargin);
animatingView.setLayoutParams(params2);
if(animationListener != null) {
animationListener.onAnimationEnd(animation);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
if(animationListener != null) {
animationListener.onAnimationRepeat(animation);
}
}
};
@Override
public boolean willChangeBounds() {
return true;
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
this.width = width;
// calculate position of image center
/*int cxImage = width / 2;
int cyImage = height / 2;
cx = view.getLeft() + cxImage;
cy = view.getTop() + cyImage;*/
cx = rotationAnchorView.getWidth() / 2.0f;
cy = animatingView.getHeight() / 2.0f;
if (r == 0) {
r = cx;
}
// set previous position to center
prevX = cx;
prevY = cy;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (interpolatedTime == 0) {
t.getMatrix().setTranslate(prevDx, prevDy);
return;
}
float angleDeg = (interpolatedTime * 1800f + startAngle) % 1800f;
float angleRad = (float) Math.toRadians(angleDeg);
Log.d("CVA", "interpolatedTime : " + interpolatedTime);
Log.d("CVA", "angleDeg : " + angleDeg);
// r = radius, cx and cy = center point, a = angle (radians)
float x = (float) (cx + r * Math.cos(angleRad));
float y = (float) (cy + r * Math.sin(angleRad));
if (!isRadiusConstant) {
r = r - (r * interpolatedTime / 200.0f);
}
if (r < width / 2) {
r = width / 2;
}
float dx = prevX - x;
float dy = prevY - y;
prevX = x;
prevY = y;
prevDx = dx;
prevDy = dy;
t.getMatrix().setTranslate(dx, dy);
if (onTransformationListener != null) {
onTransformationListener.onTransform(dx, dy);
}
}
public float getPrevDx() {
return prevDx;
}
public void setPrevDx(float prevDx) {
this.prevDx = prevDx;
}
public float getPrevDy() {
return prevDy;
}
public void setPrevDy(float prevDy) {
this.prevDy = prevDy;
}
public boolean isRadiusConstant() {
return isRadiusConstant;
}
public void setRadiusConstant(boolean radiusConstant) {
isRadiusConstant = radiusConstant;
}
}
//Use case iv1 will move in circle to icCircle
final CircularPropertyAnimation anim = new CircularPropertyAnimation(iv1, ivCircle, 0);
anim.setInterpolator(new LinearInterpolator());
anim.setDuration(11000);
//anim.setRepeatCount(100);
iv1.startAnimation(anim);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment