How to move an image across the screen android?
Guys, im creating MoleMash game for My Coursework and I really need help!. I want to try to move a image (the mole) across the screen in different and random coordinates so that it can be touched by the user to get a score. I created the background which I made the image view. I have the mole, Is it another image view? or is it a Image button?
And how do I move this across to different parts of the screen for the user interact?
I would greatly appreciate your help!
For games development you need to learn how to use canvas and SurfaceView: How can I use the animation framework inside the canvas?
Using onTouch event listener you would compare the touch location with the location of your animated images...
The mole would be an image button so it could be clicked, but to make it move you would have to use animation. Keep in mind that I am a beginner in Android animation as well :). You would probably use TranslateAnimation and set the x and y in the parameters to random variables, the duration could be when a time/counter variable reaches a certain point after the game has started. This post has more information on animation: How to move an image from left to right in android.
Try this code,
declare following variables
private Random random=new Random();
private int screenwidth, screenhgt;
In onCreate():
screenwidth= getyourScreenWidth;
screenhgt=getyourscreenheight;
Pass your view to this method(In my case I animate textview.. you pass the imageview)
private void screenRandomAnimator(final TextView textView) {
final AnimatorSet mAnimatorSet = new AnimatorSet();
mAnimatorSet.playTogether(ObjectAnimator.ofFloat(textView, "x", (float) random.nextInt(screenwidth), (float) random.nextInt(screenwidth)),
ObjectAnimator.ofFloat(textView, "y", (float) random.nextInt(screenhgt), (float) random.nextInt(screenhgt)), ObjectAnimator.ofFloat(textView, "rotation", 360)
/* ObjectAnimator.ofFloat(textView, "scaleX", 1, 0.8f, 1, 1.1f, 1), ObjectAnimator.ofFloat(textView, "scaleY", 1, 0.8f, 1, 1.1f, 1)*/);
int Low = 1500;
int High = 2500;
int Result = random.nextInt(High - Low) + Low;
mAnimatorSet.setDuration(Result);
mAnimatorSet.start();
mAnimatorSet.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
mAnimatorSet.playTogether(ObjectAnimator.ofFloat(textView, "x", textView.getX(), (float) random.nextInt(screenwidth)),
ObjectAnimator.ofFloat(textView, "y", textView.getY(), (float) random.nextInt(screenhgt)));
int Low = 1500;
int High = 2500;
int Result = random.nextInt(High - Low) + Low;
mAnimatorSet.setDuration(Result);
mAnimatorSet.start();
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
}
Related
Hello Stack community,
I want to change the position of text view.
I have tried several ways, but for all of them, the view position is set back to original position.
The ways I tried,
// 1. way
someText.setX(newPositionX);
someText.setY(newPositionY);
// 2.way
someText.x(newPositionX).y(newPositionY).setDuration(0).start();
// 3.way
someText.animate().x(newPositionX).y(newPositionY).setDuration(0).start();
//4.way
ObjectAnimator objectAnimatorX= ObjectAnimator.ofFloat(someText, "translationX", oldPositionX, newPositionX);
ObjectAnimator objectAnimatorY= ObjectAnimator.ofFloat(someText, "translationY", oldPositionY, newPositionY);
objectAnimatorX.setDuration(0);
objectAnimatorX.start();
objectAnimatorY.setDuration(0);
objectAnimatorY.start();
// 5.way
ObjectAnimator animX = ObjectAnimator.ofFloat(someText, "x", newPositionX);
ObjectAnimator animY = ObjectAnimator.ofFloat(someText, "y", newPositionY);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();
For all these ways, it is reset to original place.
However when I use animate function in onTouch event eg. someText.animate().x(newPositionX).y(newPositionY).setDuration(0).start();
it does not set to original coordinate, the change is permanent. This what i want but I want to do this, without touch event, namely some other part of the code which uses some other events.
My questions are
Why the change is permanent when I use onTouch event while it is temporary when I dont use onTouch event?
How can I achieve to set Text position permanently?
Lastly my xml is like this for textView
`<TextView
android:id="#+id/latinBigTextView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"
android:background="#drawable/border_text"
android:text="Initial text " />`
Somehow I have fixed. I have not still got the best results but it updates permanently. Most probably because of my calculations but for now it seems that the position update remains. I have used following code:
TranslateAnimation anim = new TranslateAnimation(0, deltaX, 0, deltaY);
anim.setDuration(0);
anim.setFillAfter(true);
anim.setFillEnabled(true);
anim.setAnimationListener(new Animation.AnimationListener()
{
#Override
public void onAnimationStart(Animation animation)
{
}
#Override
public void onAnimationEnd(Animation animation)
{
int l = newPosX;
int t = newPosY;
int r = SomeText.getWidth() + newPosX;
int b = SomeText.getHeight() + newPosY;
latinText.layout(l, t, r, b);
}
#Override
public void onAnimationRepeat(Animation animation)
{
}
});
latinText.startAnimation(anim);
Where SomeText is the textView which I want to move permanently and dynamically. DeltaX and DeltaY is the amount of pixel that I want to move.
(l, r, t, b) means (left, top, right, bottom) of the view.
I hope it helps other people who have faced the same problem.
However I have still no answer for my first question. If anyone knows and tells, I would be very appreciated.
I am trying to implement activity transitions in my app. I came across an awesome one here. But it is only compatible with android jellybean +. The link above redirects to youtube where Nick Butcher shows Activity zoom transition from a view.
I want to use it on gingerbread (API 10)+. How can I achieve that? One idea which came to my mind was to take the location of that view on the screen, pass it to the upcoming activity and then ask that upcoming activity to zoom or grow bigger from that location. I don't know if that is possible or not. Any ideas or solutions are greatly appreciated.
Thanks!
You can use this animation, and change XY according to your image position and screen size, and start your activity when the animation end, it's a trick, hope it help:
private void centerAndZoomView( View view)
{
RelativeLayout root = (RelativeLayout) findViewById( R.id.rootLayout );
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics( dm );
int statusBarOffset = dm.heightPixels - root.getMeasuredHeight();
int originalPos[] = new int[2];
view.getLocationOnScreen( originalPos );
int xDest = dm.widthPixels/2;
xDest -= (view.getMeasuredWidth()/2);
int yDest = dm.heightPixels/2 - (view.getMeasuredHeight()/2) - statusBarOffset;
TranslateAnimation anim = new TranslateAnimation( 0, xDest - originalPos[0] , 0, yDest - originalPos[1] );
Animation scale
= new ScaleAnimation(1.0f,root.getMeasuredWidth()/view.getMeasuredWidth() , 1.0f, root.getMeasuredHeight()/view.getMeasuredHeight(),
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
scale.setInterpolator(new AccelerateInterpolator());
AnimationSet set = new AnimationSet(false);
set.addAnimation(scale);
set.addAnimation(anim);
set.setFillAfter(true);
set.setDuration(10000);
//set.start();
view.startAnimation(set);
set.setAnimationListener(new AnimationListener()
{
#Override
public void onAnimationStart(Animation animation){}
#Override
public void onAnimationRepeat(Animation animation){}
#Override
public void onAnimationEnd(Animation animation)
{
Intent intent = new Intent(getApplication(), NextActivity.class);
startActivity(intent);
Toast.makeText(getApplicationContext(), "END OF ANIMATION", Toast.LENGTH_LONG).show();
}
});
}
I've combined TranslateAnimation and ScaleAnimation according to the screen width and height, you can pass any View(Button, ImageView, LinarLayout...) as parameter, and your root layout must have "rootLayout" id.
You can use the Activity.overridePendingTransition() method and specify your own animations. This has been available since API level 5. The ActivityOptions Nick is using in the video is just a newer way of accomplishing the same thing and was introduced in API level 16. Note that in order to support the older APIs you'll have to use an Animation resource (tween animation) instead of an Animator type. You can do translation, alpha and zoom (scale) type animations.
I am working on Android onlineShopping application.I have to apply some animation.
cart image is displays on Right-top corner of the screen.
List of items are on screen each item with "Add to cart" button.
When user press this button I have to play animation.
I have one fix image which should animate from touch position to
cart-image placed on right-top corner of the screen.
Please help me out.
Thanks in advance.
Update :
I Tried this to move image from one place to another.
TranslateAnimation anim = new TranslateAnimation(0,0,200,200);
anim.setDuration(3000);
img.startAnimation(anim);
This image I want to animate from touch position to right-top corner.
ultimately you want to move a view from one position to another position with animation.
Step 1:
get initial position of that view
int fromLoc[] = new int[2];
v.getLocationOnScreen(fromLoc);
float startX = fromLoc[0];
float startY = fromLoc[1];
Step 2:
get destination position
int toLoc[] = new int[2];
desti.getLocationOnScreen(toLoc);
float destX = toLoc[0];
float destY = toLoc[1];
Step 3:
create a class to manage animation
public class Animations {
public Animation fromAtoB(float fromX, float fromY, float toX, float toY, AnimationListener l, int speed){
Animation fromAtoB = new TranslateAnimation(
Animation.ABSOLUTE, //from xType
fromX,
Animation.ABSOLUTE, //to xType
toX,
Animation.ABSOLUTE, //from yType
fromY,
Animation.ABSOLUTE, //to yType
toY
);
fromAtoB.setDuration(speed);
fromAtoB.setInterpolator(new AnticipateOvershootInterpolator(1.0f));
if(l != null)
fromAtoB.setAnimationListener(l);
return fromAtoB;
}
}
Step 4:
add animationlistener and start animation on desired view
AnimationListener animL = new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
//this is just a method call you can create to delete the animated view or hide it until you need it again.
clearAnimation();
}
};
//now start animation as mentioned below:
Animations anim = new Animations();
Animation a = anim.fromAtoB(startX, startY, destX, destY, animL,850);
v.setAnimation(a);
a.startNow();
I hope it will be helpful !!
I think you are exactly looking for, you can check link
link here
check this example hope this will help u:
http://developer.android.com/training/animation/zoom.html
I have created a 3D flip of a view using this android tutorial
However, I have done it programmatically and I would like to do it all in xml, if possible. I am not talking about simply shrinking a view to the middle and then back out, but an actual 3D flip.
Is this possible via xml?
Here is the answer, though it only works with 3.0 and above.
1) Create a new resources folder called "animator".
2) Create a new .xml file which I will call "flipping". Use the following xml code:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="0" android:valueTo="360" android:propertyName="rotationY" >
</objectAnimator>
No, the objectAnimator tags do not start with an uppercase "O".
3) Start the animation with the following code:
ObjectAnimator anim = (ObjectAnimator) AnimatorInflater.loadAnimator(mContext, R.animator.flipping);
anim.setTarget(A View Object reference goes here i.e. ImageView);
anim.setDuration(3000);
anim.start();
I got all this from here.
Since the answers to this question are fairly dated, here is a more modern solution relying on ValueAnimators.
This solution implements a true, visually appealing 3D-flip, because it not just flips the view, but also scales it while it is flipping (this is how Apple does it).
First we set up the ValueAnimator:
mFlipAnimator = ValueAnimator.ofFloat(0f, 1f);
mFlipAnimator.addUpdateListener(new FlipListener(frontView, backView));
And the corresponding update listener:
public class FlipListener implements ValueAnimator.AnimatorUpdateListener {
private final View mFrontView;
private final View mBackView;
private boolean mFlipped;
public FlipListener(final View front, final View back) {
this.mFrontView = front;
this.mBackView = back;
this.mBackView.setVisibility(View.GONE);
}
#Override
public void onAnimationUpdate(final ValueAnimator animation) {
final float value = animation.getAnimatedFraction();
final float scaleValue = 0.625f + (1.5f * (value - 0.5f) * (value - 0.5f));
if(value <= 0.5f){
this.mFrontView.setRotationY(180 * value);
this.mFrontView.setScaleX(scaleValue);
this.mFrontView.setScaleY(scaleValue);
if(mFlipped){
setStateFlipped(false);
}
} else {
this.mBackView.setRotationY(-180 * (1f- value));
this.mBackView.setScaleX(scaleValue);
this.mBackView.setScaleY(scaleValue);
if(!mFlipped){
setStateFlipped(true);
}
}
}
private void setStateFlipped(boolean flipped) {
mFlipped = flipped;
this.mFrontView.setVisibility(flipped ? View.GONE : View.VISIBLE);
this.mBackView.setVisibility(flipped ? View.VISIBLE : View.GONE);
}
}
That's it!
After this setup you can flip the views by calling
mFlipAnimator.start();
and reverse the flip by calling
mFlipAnimator.reverse();
If you want to check if the view is flipped, implement and call this function:
private boolean isFlipped() {
return mFlipAnimator.getAnimatedFraction() == 1;
}
You can also check if the view is currently flipping by implementing this method:
private boolean isFlipping() {
final float currentValue = mFlipAnimator.getAnimatedFraction();
return (currentValue < 1 && currentValue > 0);
}
You can combine the above functions to implement a nice function to toggle the flip, depending on if it is flipped or not:
private void toggleFlip() {
if(isFlipped()){
mFlipAnimator.reverse();
} else {
mFlipAnimator.start();
}
}
That's it! Simple and easy. Enjoy!
I have created a simple program for creating flip of view like :
In Activity you have to create this method, for adding flip_rotation in view.
private void applyRotation(View view)
{
final Flip3dAnimation rotation = new Flip3dAnimation(view);
rotation.applyPropertiesInRotation();
view.startAnimation(rotation);
}
for this, you have to copy main class used to provide flip_rotation.
import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;
public class Flip3dAnimation extends Animation {
private final float mFromDegrees;
private final float mToDegrees;
private final float mCenterX;
private final float mCenterY;
private Camera mCamera;
public Flip3dAnimation(View view) {
mFromDegrees = 0;
mToDegrees = 720;
mCenterX = view.getWidth() / 2.0f;
mCenterY = view.getHeight() / 2.0f;
}
#Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}
public void applyPropertiesInRotation()
{
this.setDuration(2000);
this.setFillAfter(true);
this.setInterpolator(new AccelerateInterpolator());
}
#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();
Log.e("Degree",""+degrees) ;
Log.e("centerX",""+centerX) ;
Log.e("centerY",""+centerY) ;
camera.rotateY(degrees);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
The tutorial or the link by om252345 don't produce believable 3D flips. A simple rotation on the y-axis isn't what's done in iOS. The zoom effect is also needed to create that nice flip feel. For that, take a look at this example.
There is also a video here.
One of the better solution to flip the image with out use of the resource animation , is as follow:-
ObjectAnimator animation = ObjectAnimator.ofFloat(YOUR_IMAGEVIEW, "rotationY", 0.0f, 360f); // HERE 360 IS THE ANGLE OF ROTATE, YOU CAN USE 90, 180 IN PLACE OF IT, ACCORDING TO YOURS REQUIREMENT
animation.setDuration(500); // HERE 500 IS THE DURATION OF THE ANIMATION, YOU CAN INCREASE OR DECREASE ACCORDING TO YOURS REQUIREMENT
animation.setInterpolator(new AccelerateDecelerateInterpolator());
animation.start();
The simplest way to do it is using ViewPropertyAnimator
mImageView.animate().rotationY(360f);
Using the fluent interface you can build more complex and exciting animation.
E.g. you can enable hardware acceleration just call withLayer() method(API 16). More here
If you want to figure out how to create 3d flick animation, please follow here and here
I implemended my own solution only for a research. It includes: cancelation, accelleration, support API >= 15 and is based on Property Animation.
The entire animation includes 4 parts, 2 for each side.
Every objectAnimator has a listener that defines current animation index and represents an image in the onAnimationStart and current play time value in the onAnimationCancel.
It looks like
mQuarterAnim1.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
mQuarterCurrentAnimStartIndex = QUARTER_ANIM_INDEX_1;
mImageView.setImageResource(mResIdFrontCard);
}
#Override
public void onAnimationCancel(Animator animation) {
mQuarterCurrentAnimPlayTime = ((ObjectAnimator) animation).getCurrentPlayTime();
}
});
For start set call
mAnimatorSet.play(mQuarterAnim1).before(mQuarterAnim2)
If AnimatorSet was canceled we can calculate delta and run the reverse animation relying on the current index animation and the current play time value.
long degreeDelta = mQuarterCurrentAnimPlayTime * QUARTER_ROTATE / QUARTER_ANIM_DURATION;
if (mQuarterCurrentAnimStartIndex == QUARTER_ANIM_INDEX_1) {
mQuarterAnim4.setFloatValues(degreeDelta, QUARTER_FROM_1);
mQuarterAnim4.setDuration(mQuarterCurrentAnimPlayTime);
mAnimatorSet.play(mQuarterAnim4);
}
A full code snippet you can find here
Just put the view which you're going to animate it in place of viewToFlip.
ObjectAnimator flip = ObjectAnimator.ofFloat(viewToFlip, "rotationY", 0f, 360f); // or rotationX
flip.setDuration(2000); // 2 seconds
flip.start();
Adding to A. Steenbergen's great answer. When flipping the same view (updating a TextView for example) I removed the View.Visibility change in the constructor in order to keep the transition smoother.
public FlipListener(final View front, final View back) {
this.mFrontView = front;
this.mBackView = back;
}
I want to rotate an imageview from 30 degrees on each click on a button.
On the first clic, i can set the animation properly but i can't succeed to update the imageview position after the animation. When i clicked again on the button, the animation start from the original position of the imageview and not from the final position after the first animation.
Here is my code :
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
turnImg = (ImageView) findViewById(R.id.imageViewturnImg );
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.imgTurn);
// Getting width & height of the given image.
int w = bmp.getWidth();
int h = bmp.getHeight();
turnImg .setImageBitmap(bmp);
Button buttonok = (Button) findViewById(R.id.buttonok);
buttonok.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
turn();
}
});
}
public void turn()
{
float degrees = 30;
RotateAnimation anim = new RotateAnimation(0, degrees,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);
anim.setInterpolator(new LinearInterpolator());
anim.setDuration(300);
anim.setFillEnabled(true);
anim.setFillAfter(true);
anim.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation arg0) {
Matrix mat = turnImg.getImageMatrix();
mat.postRotate(30,turnImg.getWidth()/2, turnImg.getHeight()/2);
turnImg.setScaleType(ScaleType.MATRIX);
turnImg.setImageMatrix(mat);
}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationStart(Animation animation) {}
});
turnImg.startAnimation(anim);
}
I think the problem came from the way i actualize the position in the onAnimationEnd().
ps : sorry for my bad english...
The problem is that your animation is not affecting the same object as your matrix rotation. That is, you are animating the rotation of the ImageView object, but then you are setting the rotation of the image that is within that ImageView object. So, for example, the first time you rotate it, the ImageView rotates from 0 to 30 degrees, and then remains at a rotation of 30 degrees due to the call to setFillAfter(true). Then the onAnimationEnd() handler runs, which rotates the internal image by 30 degrees. This effectively jumps the image to a rotation of 60 degrees, as seen by the user (30 for the View, 30 for the bitmap). Then the next time the animation runs, it rotates the view from 0 to 30 degrees, with the internal image still at its rotation of 30 degrees. This makes it look to the user like it's rotating from 30 to 60 degrees. Then you apply another rotation on the internal image when that animation finishes, ending up with the image rotated to 60 degrees and the view rotated (again) to 30 degrees, so the image is now visually rotated to 90 degrees.
And so on.
There are different ways to handle this problem, but one simple way is to avoid affecting the two different objects - just work with the ImageView. Instead of rotating from 0 to 30 each time, rotate from whatever the current rotation is to that value plus 30 degrees. You can remove the onAnimationEnd() handler, because you will no longer need to rotate the image inside the view.
The resulting code for turn() is much simpler:
public void turn()
{
RotateAnimation anim = new RotateAnimation(currentRotation, currentRotation + 30,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);
currentRotation = (currentRotation + 30) % 360;
anim.setInterpolator(new LinearInterpolator());
anim.setDuration(1000);
anim.setFillEnabled(true);
anim.setFillAfter(true);
turnImg.startAnimation(anim);
}
This code assumes an instance variable of currentRotation, which is used to track the last degrees the view was rotated to.
Its a bit more involved if you allow the user to click mid-animation, but not too difficult.
By the way, this is much simpler in the animation system in 3.0; there is now a 'rotation' property on View, and you can run an animation on that property and it can track its own current value. But the approach above should work for older releases.