Last active
June 13, 2016 06:55
-
-
Save vaibhav-jani/680dd710c00dad9ba9ccd25a7c35758e to your computer and use it in GitHub Desktop.
Animation : Rotate view across another view
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //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