I have implemented image rotate animation on the audio player screen where when audio start than image rotation and when a user clicks on pause button animation stop, I use clearAnimation() method for stopping animation and when user resume I call startAnimation() method but this Look bad because when I clear animation image degree like 90 was different and when I startAnimation() again its starting point was 0. please check this video where animation having an issue while play/pause audio Watch This Video.
So I find a pause()/resume() animation for better smoothness. Can anyone help me to sort out animation smoothness or working batter?
Use Animator object to animate the view's property (like android:rotation):
View imgView = findViewById(R.id.image);
View playPauseBtn = findViewById(R.id.button);
final ObjectAnimator anim = ObjectAnimator.ofFloat(imgView, View.ROTATION, 0f, 90f)
.setDuration(4000);
anim.setRepeatCount(Animation.INFINITE);
anim.setInterpolator(new LinearInterpolator());
anim.start();
playPauseBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (anim.isPaused()) {
anim.resume();
} else {
anim.pause();
}
}
});
Related
I am developing two different animations as shown below.
The first animation I was able to develop using Object animator and FrameLayout. Basically, I created the two rectangles and the candlesticks inside a gravity-centered frame layout. When made to start the animation, I used the object animator to move them on either side and return to the initial position.
My second animation is the issue point here. In this animation, the rectangles will go on a circular path from their initial point and return back to their initial point. During this course, the candles need to move in sync with the rectangle giving a spring effect (or) kind of a sliced rectangle.
My initial idea was to re-use the first animation and just as the first animation runs, I would run a rotate animation on the frameLayout view.
But that doesn't seem to work wherein rotation works but the translation doesn't.
Can someone say if I have taken the right approach or should I use some other way to achieve this?
Adding the code that I have tried, but didn't work.
Animation anim = new RotateAnimation(0.0f, 360.0f, pivotX, pivotY);
anim.setDuration(500);
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
for(View view : mCandleSticks) {
ObjectAnimator anim1 = ObjectAnimator.ofFloat(view, "translationX", view.getX(), targetPos, view.getX());
anim1.setDuration(500);//set duration
anim1.start();//start animation
}
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
});
frameLayout.startAnimation(anim);
Thanks in advance.
I'd like to translate view with ObjectAnimator twice, but the "X" position gets back to starting position after pressing the button again, how can i make it continue, and move further right in this case?
final ObjectAnimator animation = ObjectAnimator.ofFloat(button, "translationX", 100f);
animation.setDuration(2000);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
animation.start();
}
});
The reason your button jumps back to its starting position is covered in the documentation for the ofFloat() method:
A single value implies that that value is the one being animated to, in which case the start value will be derived from the property being animated and the target object when start() is called for the first time.
Because you're reusing the same ObjectAnimator instance every time, the translationX property is animated from its original (0) to the passed in argument (100) every time.
However, you can't just change it to create a new ObjectAnimator and have that solve everything. Let's say you changed your code to this:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final ObjectAnimator animation = ObjectAnimator.ofFloat(button, "translationX", 100f);
animation.setDuration(2000);
animation.start();
}
});
That would change what happens, but still not give you what you want. Now the button would slide from 0 to 100 the first time, but would remain stationary every time after that.
Why?
Because after the first animation, the translationX property is 100. So now you're animating between 100 and 100 (instead of 0 and 100)... which doesn't do anything.
The solution is to animate from the view's current translationX to the current value + 100. And to do that every time, instead of re-using the same ObjectAnimator over and over.
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
float end = button.getTranslationX() + 100;
ObjectAnimator animation = ObjectAnimator.ofFloat(button, "translationX", end);
animation.setDuration(2000);
animation.start();
}
});
button.animate().translationX(button.translationX + 100f).setDuration(1000).start()
Works like a charm
So i got this Rotation Animation:
rotate = new RotateAnimation(0f, -270f,200,200);
rotate.setDuration(2000);
rotate.setFillAfter(true);
and i have Button that start the animation on click
public void click(View view){
Image.startAnimation(rotate);
}
and when i click on button animation starts correctly and ends on needed state. but when i click second time it begin from state it was before any animation.
Question:
how can i start animation from the state it ends?
Object Animator instead
ObjectAnimator imageViewObjectAnimator = ObjectAnimator.ofFloat(imageview ,
"rotation", 0f, -270f);
imageViewObjectAnimator.setDuration(2000);
imageViewObjectAnimator.start();
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.
Here is my scenario.
At first I do an animation set to my view (View.startAnimation(animationSet)) where animationSet consists of Translate + Rotate + Scale all at the same time. It works fine.
on that animationSet I have fillAfter(true).
After some time user click on a button and onClick I must start new ScaleAnimation on that same View. So if I do something like:
#Override
public void onClick(View v) {
ScaleAnimation scaleAnimation = new ScaleAnimation(mOldScaleFactor, mScaleFactor, mOldScaleFactor, mScaleFactor, mPivotX, mPivotY);
scaleAnimation.setDuration(ANIMATION_DURATION_MILIS);
scaleAnimation.setStartOffset(ANIMATION_OFFSET_MILIS);
scaleAnimation.setFillAfter(true);
v.startAnimation(scaleAnimation);
}
All the previous animation (Translate + Rotete + Scale) is forgotten.
How to start new animation from where old animation ends?
You could try to implement a listener and possible capture the information from when the previous animation left off, however I'm not sure you'll be able to query the animation for its state. Another option is to make sure the animation stops into a known state. That way you can know how you need to start the next animation.
public float param1;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
//load text view to add animation
ImageView image1 = (ImageView) findViewById(R.id.splash_imageView1);
Animation fade1 = AnimationUtils.loadAnimation(this, R.anim.fade_anim);
image1.startAnimation(fade1);
fade1.setAnimationListener(new AnimationListener() {
public void onAnimationEnd(Animation animation) {
//interrogate animation here
}