I have a mixture of animations running on various scenarios.
As an example;
I have a fade-in and fade-out animator on a small circle bitmap. On ACTION_DOWN the fade-in should start
and on ACTION_UP, when the fade-in ends, fade-out should run. BUT, if the user picks up the finger before the fade-in ends, it should stop right there (fadein.cancel()), fade-out should start from THAT alpha value.
I dont want a new object animator each time, I defined an animator like this in the constructor
fadein = Objectanimator.ofFloat(bitmap, "alpha", 1.0f);
fadeOut = Objectanimator.ofFloat(bitmap, "alpha", 0.0f);
What happens is, if I produce the issue as mentioned (picking up the finger fast), the fadeout animator will pick up the alpha value where fade-in left off and it'll RETAIN that. That is, 2nd time onwards it'll NOT pick up a new alpha! Why is that? Whats the workaround? Create new objects each time?
ObjectAnimator class modifies the attributes of the view, so it updates the property of the view using the setter method of the Object property (as per official Android Guide).
So, when fadein animation runs, the alpha value is constantly modified, and when fadein.cancel() executes, the alpha value of the View stops updating. Let's say this value is X.
So, when you start fadeOut, it animates from X to 0.0f.
Whats the workaround?
For fadeOut, use two values imply a starting and ending values
fadeOut = Objectanimator.ofFloat(bitmap, "alpha", 1.0f, 0.0f);
Related
I want to display a buttons with animations like fade-in along with the translate animation programmatically. I have to start translate animation from a specific position on the screen. So i need to pass the x and y values for the translate animation to start from.
Im using the following code for translate animation but how to add fade-in animation to the existing translate animation?
TranslateAnimation tanim = new TranslateAnimation(
TranslateAnimation.ABSOLUTE, getIntent().getFloatExtra("ButtonX", maxX),
TranslateAnimation.ABSOLUTE, 0,
TranslateAnimation.ABSOLUTE, getIntent().getFloatExtra("ButtonY", 0),
TranslateAnimation.ABSOLUTE, 100);
tanim.setDuration(3000);
I've used Animations several times before and they always left me scratching my head. Some things I would recommend you should look into are Object Animators and Animator Sets. They're really useful, as they allow you to animate any property of the given view. As long as the view has a setter method for that property, you can add it to the animator set by passing in the string name of the property to the Animator constructor. The AnimatorSet class also allows you to easily choreograph multiple animations.
In your case, you could do something roughly like the following:
AnimatorSet animations = new AnimatorSet();
Animator xAnim = ObjectAnimator.ofFloat(button, "translationX", finalXValue);
xAnim.setDuration(3000);
Animator yAnim = ObjectAnimator.ofFloat(button, "translationY", finalYValue);
yAnim.setDuration(3000);
Animator alphaAnim = ObjectAnimator.ofFloat(button, "alpha", finalAlphaValue);
alphaAnim.setDuration(alphaDuration);
//Play all the animations together
animations.play(xAnim).with(yAnim).with(alphaAnim);
You can string together as many animators as you want this way, and you can also set animators to be played in a sequence using the .before() and .after() methods rather than the .with() method.
I am trying to create a mirror reflection of a view, for that I tired the Y axis ObjectAnimator animation using the following code:
ObjectAnimator animation = ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360f);
animation.setDuration(3600);
animation.setRepeatCount(ObjectAnimator.INFINITE);
animation.setInterpolator(new AccelerateDecelerateInterpolator());
animation.start();
This works perfectly but I want the animation to stop after reaching the desired end position rather than returning back to the original place.
After some research I found that setting the setFillAfter(boolean) method of Animation object to true does that thing.
Now my problem is that i am unable to convert the ObjectAnimator animation to a standard Animation code. to get access to that method.
I realized i could use RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY) to rotate my view and also keep it at the ending place.
But I couldnt figure out what should be the pivotx and pivoty values so that the view stays at the same location and flips around.
Usually an ObjectAnimator stays at the desired location when the animation ends. Im guessing the line
animation.setRepeatCount(ObjectAnimator.INFINITE);
is what is making your animation start over and over in an infinite loop, remove this line and you should be fine...
I have a translate animation of an image from location1 to location2. However at any time during the animation, if a user click a button then I want to apply another translate animation from where the image at to location3 (even if the animation has not finished). Any way I can do that?
Thanks
TranslateAnimation translate = new TranslateAnimation(0, mDestLoc[0]-mSrcLoc[0], 0, mDestLoc[1]-mSrcLoc[1]);
translate.setFillAfter(true);
translate.setDuration(getDuration());
ball.startAnimation(translate);
void onbuttonClicked(){
// stop previous animation and translate image to location 3 "From where it stopped"
}
why don't you use ObjectAnimators?
You can create an animator for a particular target(or obtain the view one through animate() if you're running on a version greater-equal API level 12) and then translate, resize, fade,... your object.
If for some particular reasons the first animation is cancelled, you can call cancel and then the view will persist the current status. Then, if you create another animator based on the current values you should be able to easily perform another animation.
As we know , the android coordinate system is start from the top left corner of the android screen. The x-axis is down growth and the y-axis is right growth.But I found it's not right for the animation.
For example, I initialized the TranslateAnimation using the constructed function:
TranslateAnimation ta = new TranslateAnimation(0.0f, 200, 0.0f, 200);
Does the coordinate system have changed ? I found it didn't start from the top left corner.
Then I initialized the other translateAnimation for moving up and right direction :
TranslateAnimation ta = new TranslateAnimation(0.0f, 200, 0.0f, -200);
ta.setReaptMode(Animation.REVERSE);
The same behavior would be found.
I am confused about it.
I believe that constructor for TranslateAnimation uses deltas. See this. Or look at the constructor sig. : (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta). So if you want your anim. to jump up first, you could use a negative third ctor param.
More precisely:
An animation can never start until after the layout has been measured. One usually shouldn't have to worry about how this works beyond that the algorithm is mostly very good and you can take control of its strategies by setting layout parameters. In short, by the time an animation might be started, we know where you want the view to be on the screen, because you set layout parameters.
Translate animation then takes deltas from that position. So your current animation shouldn't start from the top left, but rather wherever those layout params were evaluated by onMeasure.
Some would say- how annoying. It's gonna get complicated even if you just want to do some simple up-down type animations... Well, here's an advisable development strategy; it snould make android animation development a breeeze. Set an animationListener on every animation. In onAnimationEnd, in possibly a parametized way, reset the layout parameters on the view your animating to where you expect it to be. That way, you'll get no surprising "jumps" when you re-apply an animation again. You may need to invalidate in some circumstances, or clearAnimation. The reason that this works is that the measure pass will be caused to come round again and you'll have a new offset for your TranslateAnimation. Finally, you may want to do all this resetting posted to the message queue of a view using post(Runnable runnable) in the listener, so you're off the last pass of the animation draw.
I too found android Animations can occasionally surprise you and cause jumpy behaviour. But if you do it like this, constructors taking delta params shouldn't be confusing again.
I am trying to make my own progressdialog, sort of. I'm just using a Dialog which inflates a Layout. In this layout, I have an ImageView, this imageview should rotate just like the original spinner in the ProgressDialog. I applied this animation to it:
RotateAnimation r = new RotateAnimation(ROTATE_FROM, ROTATE_TO, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
r.setDuration(10000);
r.setRepeatCount(r.INFINITE);
icon.startAnimation(r);
The animation last for 10000 ms obviously. The animation start slowly and ends slowly, is it possible that the rotation speed is constant at all time?
You can set a LinearInterpolator to the animation:
r.setInterpolator(new LinearInterpolator());
A way to increase speed rotation is to set a duration and a number in repeatCount field that apply to you. Doing so, you can control the speed... Just put some big big numbers and add a listener to your animation and when it ends, start it again if dialog is still displayed.