I am using this Rotate3dAnimation class to create a flipping coin animation which is also moving and scaling. But i can use it only with one image view. By just using startAnimation() method on that image view.
But What i want to do is, to use two sides of a coin so it will look like a real coin with two different sides is flipping. Can someone help me about how to do that?
Thanks
package com.example.movingcoin;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.graphics.Camera;
import android.graphics.Matrix;
/**
* An animation that rotates the view on the Y axis between two specified angles.
* This animation also adds a translation on the Z axis (depth) to improve the effect.
*/
public class Rotate3dAnimation extends Animation {
private final float mFromDegrees;
private final float mToDegrees;
private final float mCenterX;
private final float mCenterY;
private final float mDepthZ;
private final boolean mReverse;
private Camera mCamera;
/**
* Creates a new 3D rotation on the Y axis. The rotation is defined by its
* start angle and its end angle. Both angles are in degrees. The rotation
* is performed around a center point on the 2D space, definied by a pair
* of X and Y coordinates, called centerX and centerY. When the animation
* starts, a translation on the Z axis (depth) is performed. The length
* of the translation can be specified, as well as whether the translation
* should be reversed in time.
*
* #param fromDegrees the start angle of the 3D rotation
* #param toDegrees the end angle of the 3D rotation
* #param centerX the X center of the 3D rotation
* #param centerY the Y center of the 3D rotation
* #param reverse true if the translation should be reversed, false otherwise
*/
public Rotate3dAnimation(float fromDegrees, float toDegrees,
float centerX, float centerY, float depthZ, boolean reverse) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mCenterX = centerX;
mCenterY = centerY;
mDepthZ = depthZ;
mReverse = reverse;
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
final Matrix matrix = t.getMatrix();
camera.save();
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
// camera.rotateY(degrees);
camera.rotateX(degrees);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
faced the same problem few days ago, found the solution in class FlipAnimator that you can find here: FlipAnimatorClass
it is pretty easy, actually: you just have to pass to FlipAnimator the two sides of the coin. The class is pretty easy to understand, I think, and it is practically doing what g00dy suggested in his comment above.
the trick is to rotate your view twice !
once from normal position to middle, change your view (eg. change the image of your coin) and then rotate it back from middle to normal.
you should do all the changes in view and starting rotation from middle to normal in the onAnimationEnd in AnimationListener of the first animation !
like this:
firstAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
findViewById(R.id.conceptsLay).setVisibility(View.GONE);
findViewById(R.id.factBaseLay).setVisibility(View.VISIBLE);
secondAnimation.startAnimation();
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
in the code above, I first rotate the conceptsLay to middle, where its basically invisible, then make it GONE and make the other examples view VISIBILE and start its animation from middle to normal!
so what the user sees is that the view is flipped !
needles to say that, first you will rotate it from 0 to 90, and then in secondAnimation, you will rotate it -90 to 0 !
also for making it smoother I've added some alpha animations as well!
hope it will help
Related
I am developing a game using libgdx and i want to draw a smooth line using shape renderer.
shaperenderer.begin(ShapeType.Line);
shaperenderer.line(fisrstVec2,secondVec2);
shaperenderer.end();
I have tried Multi Sample anti aliasing from libgdx blog.
I have also went through Anti aliased filed shape in libgdx
but unfortunately these line is not in latest verson of libgdx.
Gdx.gl.glEnable(GL10.GL_LINE_SMOOTH);
Gdx.gl.glEnable(GL10.GL_POINT_SMOOTH);
Enable anti-alising in the configuration:
For Desktop:
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.samples = 2;
new LwjglApplication(new MyGdxGame(Helper.arrayList(arg)), config);
For Android:
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
config.numSamples = 2;
initialize(new MyGdxGame(null), config);
Or you could create a white pixmap of 1x1 and use it to create a sprite and draw the line using that sprite, I personally prefer this method istead of ShapeRenderer (note that there is no rotation in this method):
/**
* draws a line on the given axis between given points
*
* #param batch spriteBatch
* #param axis axis of the line, vertical or horizontal
* #param x x position of the start of the line
* #param y y position of the start of the line
* #param widthHeight width or height of the line according to the axis
* #param thickness thickness of the line
* #param color color of the line, if the color is null, color will not be changed.
*/
public static void line(SpriteBatch batch, Axis axis, float x, float y, float widthHeight, float thickness, Color color, float alpha) {
if (color != null) sprite.setColor(color);
sprite.setAlpha(alpha);
if (axis == Axis.vertical) {
sprite.setSize(thickness, widthHeight);
} else if (axis == Axis.horizontal) {
sprite.setSize(widthHeight, 1);
}
sprite.setPosition(x,y);
sprite.draw(batch);
sprite.setAlpha(1);
}
With some modifications to the previous method, you can come up with this method to draw a line with rotation.
public static void rotationLine(SpriteBatch batch, float x1, float y1, float x2, float y2, float thickness, Color color, float alpha) {
// set color and alpha
if (color != null) sprite.setColor(color);
sprite.setAlpha(alpha);
// set origin and rotation
sprite.setOrigin(0,0);
sprite.setRotation(getDegree(x2,y2, x1, y1));
// set position and dimension
sprite.setSize(distance(x1,y1,x2,y2),thickness);
sprite.setPosition(x1, y1);
// draw
sprite.draw(batch);
// reset rotation
sprite.rotate(0);
}
public static float getDegree(float x, float y, float originX, float originY) {
float angle = (float) Math.toDegrees(Math.atan2(y - originY, x - originX));
while (angle < 0 || angle > 360)
if (angle < 0) angle += 360;
else if (angle > 360) angle -= 360;
return angle;
}
public static float distance(float x, float y, float x2, float y2) {
return (float) Math.sqrt(Math.pow((x2 - x), 2) + Math.pow((y2 - y), 2));
}
I've played with the FlipImageView project and noticed one rather curious issue. When I'm running the sample contained within the project, everything works just fine. But, when I scale the FlipImageView manually (using View.setScaleX(float) and View.setScaleY(float) methods) this sample works fine just for devices with API version 16-18, and it clips the FlipImageView during the animation to the size of the unscaled image if sample is run on the device with the 19-th version of API. Here are screenshots:
The star is clipped, API 19
The star isn't clipped, API 18
I've set the visibility of all other widgets to GONE and changed the image's width to wrap_content to make an issue even more obvious. I see this behavior both on emulators and on real devices.
The code of the custom animation looks like so:
public class FlipAnimator extends Animation {
// fields declarations omitted
public void setToDrawable(Drawable to) {
toDrawable = to;
visibilitySwapped = false;
}
public FlipAnimator() {
setFillAfter(true);
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
camera = new Camera();
this.centerX = width / 2;
this.centerY = height / 2;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final double radians = Math.PI * interpolatedTime;
float degrees = (float) (180.0 * radians / Math.PI);
if(mIsRotationReversed){
degrees = -degrees;
}
if (interpolatedTime >= 0.5f) {
if(mIsRotationReversed){ degrees += 180.f; } else{ degrees -= 180.f; }
if (!visibilitySwapped) {
setImageDrawable(toDrawable);
visibilitySwapped = true;
}
}
final Matrix matrix = t.getMatrix();
camera.save();
camera.translate(0.0f, 0.0f, (float) (150.0 * Math.sin(radians)));
camera.rotateX(mIsRotationXEnabled ? degrees : 0);
camera.rotateY(mIsRotationYEnabled ? degrees : 0);
camera.rotateZ(mIsRotationZEnabled ? degrees : 0);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
I've searched through the diff between API version 18 and 19 and didn't find any changes in the Matrix or Camera classes which are used in the Animation.applyTransformation() method. I didn't find any changes in the Animation class itself neither.
What is the source of this problem?
Upd: the clipping occurs only during the animation - when it ends, the FlipImageView is drawn in its full size.
[UPDATE]
I am just found this great article :
http://kylewbanks.com/blog/Implementing-Google-Plus-Style-ListView-Animations-on-Android
=========
I am trying to reproduce the animation which is appears in Google plus app when user scroll in bottom. Each time, the new item appears with a translation from bottom to top.
I believed that it was a 3D animation but it is not this type of animation.
=> How can i produce the Google Plus animation (translation ?) ?
Here is my actual code which works and produce a 3D animation :
In getView method :
Animation anim = new Rotate3dAnimation(90.0f, 0.0f, 100.0f, false, rowView);
anim.setDuration(500l);
rowView.startAnimation(anim);
Rotate3dAnimation class :
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.graphics.Camera;
import android.graphics.Matrix;
/**
* An animation that rotates the view on the Y axis between two specified angles.
* This animation also adds a translation on the Z axis (depth) to improve the effect.
*/
public class Rotate3dAnimation extends Animation {
private final float mFromDegrees;
private final float mToDegrees;
private final float mDepthZ;
private final View mView;
private final boolean mReverse;
private Camera mCamera;
/**
* Creates a new 3D rotation on the Y axis. The rotation is defined by its
* start angle and its end angle. Both angles are in degrees. The rotation
* is performed around a center point on the 2D space, definied by a pair
* of X and Y coordinates, called centerX and centerY. When the animation
* starts, a translation on the Z axis (depth) is performed. The length
* of the translation can be specified, as well as whether the translation
* should be reversed in time.
*
* #param fromDegrees the start angle of the 3D rotation
* #param toDegrees the end angle of the 3D rotation
* #param centerX the X center of the 3D rotation
* #param centerY the Y center of the 3D rotation
* #param reverse true if the translation should be reversed, false otherwise
*/
public Rotate3dAnimation(float fromDegrees, float toDegrees, float depthZ, boolean reverse, View view) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mDepthZ = depthZ;
mReverse = reverse;
mView = view;
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
final float centerX = mView.getWidth()/2;
final float centerY = mView.getHeight()/2;
final Camera camera = mCamera;
final Matrix matrix = t.getMatrix();
camera.save();
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
camera.rotateX(degrees);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
Try This push_up_in.xml:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="100%p" android:toYDelta="0"
android:duration="500"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:duration="500" />
</set>
Now For Implementing that:
Animation animation = AnimationUtils.loadAnimation(activity, R.anim.push_up_in);
yourlistitemView.startAnimation(animation);
I was trying to make a rotational cube using translations and rotations. I'm using a classe named Rotate3dAnimation.java provided in the Google samples. The rotation is working pretty well and i was working about making the illusion of depth on the cube while rotating making it go further and closer from the screen.
To do this i was modifying the method applyTransformation(float interpolatedTime, Transformation t) but the problem is that, the face of the cube (the one hiding while rotating) has to a movement of going further for the first half of the time, come close again at the second half.
Resuming:
Camera.translate(float x, float y, float z)
The z translate should be decreasing for the first half and increasing the second half.
Here is the code i'm using:
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
final float centerX = mCenterX;
final float centerY = mCenterY;
final String orientation = mOrientation;
final Camera camera = mCamera;
final Matrix matrix = t.getMatrix();
camera.save();
float midTime = getDuration()/2;
if (mReverse) {
camera.translate(0.0f, 0.0f, (interpolatedTime<midTime)?
(mDepthZ * interpolatedTime): (mDepthZ * (1.0f - interpolatedTime)));
} else {
camera.translate(0.0f, 0.0f, (interpolatedTime<midTime)?
(mDepthZ * (1.0f - interpolatedTime)): (mDepthZ * interpolatedTime));
}
if(orientation.equals("horizontal"))
camera.rotateY(degrees);
else
camera.rotateX(degrees);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
But i dont think this is working very well... Any sugestions?
Thanks!
I actually had the same problem and after some debugging, I realized that interpolatedTime is not in milliseconds as I (and I am guessing you) expected. This is nice so you don't really have to calculate what the midTime really is, you just need to know the progress of the interpolation.
To check if you're halfway through with the animation just use
(interpolatedTime < .5)
in your ternary statement.
i have a button defined in xml i am adding animation to it (Card Flip 3D) its works fine in google nexus one but not working properly on Kindle's.
You can see a demo here Demo Card Flip Animation this is what i am trying to achive in ANDROID.
this is my code:
public class CardFlipAnimation extends Animation {
private Camera camera;
private View fromView;
private View toView;
private float centerX;
private float centerY;
private boolean forward = true;
private boolean visibilitySwapped;
/**
* Creates a 3D flip animation between two views. If forward is true, its
* assumed that view1 is "visible" and view2 is "gone" before the animation
* starts. At the end of the animation, view1 will be "gone" and view2 will
* be "visible". If forward is false, the reverse is assumed.
*
* #param fromView First view in the transition.
* #param toView Second view in the transition.
* #param centerX The center of the views in the x-axis.
* #param centerY The center of the views in the y-axis.
* #param forward The direction of the animation.
*/
public CardFlipAnimation(View fromView, View toView, int centerX, int centerY) {
this.fromView = fromView;
this.toView = toView;
this.centerX = centerX;
this.centerY = centerY;
setDuration(500);
setFillAfter(true);
setInterpolator(new AccelerateDecelerateInterpolator());
}
public void reverse() {
forward = false;
View temp = toView;
toView = fromView;
fromView = temp;
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
camera = new Camera();
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
// Angle around the y-axis of the rotation at the given time. It is
// calculated both in radians and in the equivalent degrees.
final double radians = Math.PI * interpolatedTime;
float degrees = (float) (180.0 * radians / Math.PI);
// Once we reach the midpoint in the animation, we need to hide the
// source view and show the destination view. We also need to change
// the angle by 180 degrees so that the destination does not come in
// flipped around. This is the main problem with SDK sample, it does not
// do this.
if (interpolatedTime >= 0.5f) {
degrees -= 180.f;
if (!visibilitySwapped) {
fromView.setVisibility(View.GONE);
toView.setVisibility(View.VISIBLE);
visibilitySwapped = true;
}
}
if (forward)
degrees = -degrees;
final Matrix matrix = t.getMatrix();
camera.save();
camera.translate(0.0f, 0.0f, (float) (150.0 * Math.sin(radians)));
camera.rotateY(degrees);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
in my activity i am doing like this:
CardFlipAnimation animator = new CardFlipAnimation(button, button,
button.getWidth() / 2, Button.getHeight() / 2);
if (button.getVisibility() == View.GONE) {
animator.reverse();
}
layout.startAnimation(animator); // Relative layout with the button
What is wrong with code it works fine in some devices and not work in some devices.Is nit giving me the 3d effect.
EDIT
This link solved my problem http://www.inter-fuser.com/2009/08/android-animations-3d-flip.html
Thanks to RobinHood