Here i am trying to move a view on a path with ObjectAnimator and also need to set one more scale animation on same view.
ObjectAnimator objectAnimator = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP)
{
objectAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
}
if (objectAnimator != null) {
objectAnimator.setDuration(2500);
objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
objectAnimator.start();
view.startAnimation(scaleRection);// this is not working because changing of x y position
need to start another Animation when objectAnimator.start();
also tried with listener
objectAnimator.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
view.startAnimation(scaleRection);
}
#Override
public void onAnimationEnd(Animator animation)
{
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
You can also use an AnimatorSet play together https://developer.android.com/reference/android/animation/AnimatorSet.html#playTogether and it's builder function https://developer.android.com/reference/android/animation/AnimatorSet.Builder
To play Two ObjectAnimator together
e.g.
AnimatorSet animationSet = new AnimatorSet();
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view,"scaleY", 1f, 0f);
scaleY.setDuration(5000);
scaleY.setInterpolator(new AccelerateDecelerateInterpolator());
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view,"scaleX", 1f, 0f);
scaleX.setDuration(5000);
scaleX.setInterpolator(new AccelerateDecelerateInterpolator());
animationSet.playTogether(scaleX, scaleY);
animationSet.start();
I would suggest using ViewPropertyAnimator.
From the docs :
This class enables automatic and optimized animation of select
properties on View objects. If only one or two properties on a View
object are being animated, then using an ObjectAnimator is fine; the
property setters called by ObjectAnimator are well equipped to do the
right thing to set the property and invalidate the view appropriately.
But if several properties are animated simultaneously, or if you just
want a more convenient syntax to animate a specific property, then
ViewPropertyAnimator might be more well-suited to the task.
This class may provide better performance for several simultaneous
animations, because it will optimize invalidate calls to take place
only once for several properties instead of each animated property
independently causing its own invalidation. Also, the syntax of using
this class could be easier to use because the caller need only tell
the View object which property to animate, and the value to animate
either to or by, and this class handles the details of configuring the
underlying Animator class and starting it.
You can chain as many animations as you like at once in one line of code :
view.animate().translationX(...).translationY(...).scaleX(...).scaleY(...).setInterpolator(new AccelerateDecelerateInterpolator()).setDuration(2500);
if you need different values for your duration or similar, you can do it with two lines :
view.animate().translationX().setDuration(...) ...
view.animate().scaleX().setDuration(...) ...
There are also methods translationXBy() and scaleXBy() which might be more suitable for your case, and you can also set a listener etc. Check the docs for all available methods
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'm animating a view and I want to reset the view to the original position after animation ended.
This is what I have:
rl2 is a relativeLayout
rl2.animate().translationX(-60).translationY(117).setDuration(2000);
I tried setting this but its not working:
rl2.clearAnimation();
clearAnimation(); does not reset your animations, it just stops them and removes them from the animation queue. To undo your animations you need to actually undo them. So, for your code block you will need to call rl2.animate().translationX(0).translationY(0).setDuration(2000); to move the view back to its original position.
As #Chris Stillwell mentioned on his answer, But you can move View back to it's original position after translation animation by
rl2.animate().translationX(0).translationY(0);
I know this question was asked long time ago but someone may still look for answer.
I use the Animation class for this kind of thing; there is a setFillAfter method in this class, so you can set if you want the animation to apply its transformation after it ends.
Animation anim = new ScaleAnimation(
1f, 1f, // Start and end values for the X axis scaling
1f, 2f, // Start and end values for the Y axis scaling
Animation.RELATIVE_TO_SELF, 0f, // Pivot point of X scaling
Animation.RELATIVE_TO_SELF, 1f); // Pivot point of Y scaling
anim.setFillAfter(false); // no needed to keep the result of the animation
anim.setDuration(1000);
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
gangsterImage.startAnimation(anim);
If you're going to remove view don't use animation.removeAllListeners(), the function cannot continue that's why you will see some error. If you want to disappear a view, use View.GONE
in Kotlin like this:
animation.doOnEnd {
binding.mainLayout.visibility = View.GONE}
But by this way you couldn't remove any animation! So it' better rest them to the initial position.
binding.tvM2.animate().translationX(0f).translationY(0f).rotation(0f)
just use anim.setFillAfter(false); to reset automatically after animation ends.
enter code hereI want to implement a animation for items in a Recyclerview using ObjectAnimator. I have followed this tutorial
Here is my code for getting animations:
public static void animate(RecyclerView.ViewHolder holder, boolean direction)
{
AnimatorSet animatorSet=new AnimatorSet();
ObjectAnimator animator_Y=ObjectAnimator.ofFloat(holder.itemView,"TranslationY",direction==true ? 100 : -100,0);
animator_Y.setDuration(1000);
ObjectAnimator animator_X=ObjectAnimator.ofFloat(holder.itemView,"TranslationX",-20,20,0);
animator_X.setDuration(1000);
animatorSet.playTogether(animator_X,animator_Y);
animatorSet.start();
Log.e("animation","animation running");
}
I am calling this function from onBindViewHolder(). There is no animation from translationX and translationY. And I am sure that this method is being called everytime I scroll.
I want know that ObjectAnimator is used for Cardview or not. Thank you.`
This is my onBindViewHolder Method
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.textView.setText(data.get(position));
AnimationforAdapters.animate(holder,true);
}
Try the following code:
public static void animate(RecyclerView.ViewHolder holder, boolean direction) {
AnimatorSet animatorSet=new AnimatorSet();
ObjectAnimator animator_Y=ObjectAnimator.ofFloat(holder.itemView,"translationY",direction ? 100 : -100,0);
animator_Y.setDuration(1000);
ObjectAnimator animator_X=ObjectAnimator.ofFloat(holder.itemView,"translationX",-20,20,0);
animator_X.setDuration(1000);
animatorSet.playTogether(animator_X,animator_Y);
animatorSet.start();
Log.e("animation","animation running");
}
As mentioned in the android documentation for ObjectAnimator
This subclass of ValueAnimator provides support for animating properties on target objects. The constructors of this class take parameters to define the target object that will be animated as well as the name of the property that will be animated. Appropriate set/get functions are then determined internally and the animation will call these functions as necessary to animate the property.
So, the problem in your code was that the ObjectAnimator could not find properties TranslationX and TranslationY in your target object that can be animated.
use this its work for me :
public void slideAnimation(RecyclerView.ViewHolder holder, boolean animate) {
ObjectAnimator animatorY = ObjectAnimator.ofFloat(holder.itemView, "translationY", animate ? 40 : -40, 1f);
ObjectAnimator animatorX = ObjectAnimator.ofFloat(holder.itemView, "translationX", animate ? 40 : -40, 1f);
AnimatorSet set = new AnimatorSet();
set.playTogether(animatorX , animatorY);
set.setDuration(1000);
set.start();
}
try by maintaining reference of your row layout parent root xml tag into holder and use that instead of using holder.itemview.
Sorry guys, I have not enabled the animations in my device.Make Window animation scale,Transition animation scale,Animator duration scale to 1x inside the developer options.
Once my app reaches ~4+ animations running concurrently, the animations start to lag a little. Are there any ways I could fix/optimize that? I am using ObjectAnimator and ValueAnimator.
So, if the views are not having to redraw themselves during the animations, you can enable hardware layers during the duration of the animations. For instance:
final View myView = // your view
Animator animator = ObjectAnimator.ofFloat(myView, View.ALPHA, 0f, 1f);
animator.setDuration(1000);
animator.addAnimatorListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
myView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
#Override
public void onAnimationCancel(Animator animator) {
myView.setLayerType(View.LAYER_TYPE_NONE, null);
}
#Override
public void onAnimationEnd(Animator animator) {
// See http://stackoverflow.com/a/19615205/321697
myView.post(new Runnable() {
#Override
public void run() {
myView.setLayerType(View.LAYER_TYPE_NONE, null);
}
}
}
}
animator.start();
I'd suggest breaking that listener implementation out into a separate class, but the general idea is that you want to put the view into a hardware backed layer as soon as the animation starts (animation properties such as translation, rotation, scale, and alpha are incredibly cheap when backed by a hardware layer) and then clear the layer once the animation is complete.
In the onAnimationEnd callback, you'll notice a link to another answer where there's a bug with 4.0.x if you set the layer type to none in the onAnimationEnd callback. If you're only supporting 4.1 and above, the runnable indirection shouldn't be necessary.
EDIT: If you're animating a color transition, you probably don't want to do the above, as changing the color of the view will require it to be redrawn, causing it to rebuild the hardware layer on each frame.
If you have not used ViewPropertyAnimator, you better do. I moved and flipped(changed picture) 52 imageViews (one deck of playing cards) smoothly.
Here's an example on how to use ViewPropertyAnimator.
The question is simple but i tried to search a solution in other similar questions, and i couldn't.
I have a arraylist path containing objects of type Coordinata that is an object containing two float X and Y, that is a coordinate. In substance, it's a list of coordinate. I need my ImageView image to move on a map on my view doing several subsequential TranslateTrasformation between the coordinate contained in the list path.
This can be easily done in the case of a fixed number of translation, doing the first translate and attaching it a setAnimationListener which could catch the end of the first animation and start in that moment the second and so on. I tried to iterate the process on my list path, using a while cycle, for i cannot really know how many coordinate will be in the path when the animation will start.
The result is the animation go on for the first couple of coordinates and then jump executing the animation for the last two coordinate in the path, ignoring all that is among these.
What is going on? I'm messing up with objects?
List<Coordinata> path; // properly filled with coordinates
Coordinata coordTempStart;
Coordinata coordTempArrival;
ImageView image;
ListIterator<Coordinata> pathIterator = path.listIterator();
if(pathIterator.hasNext()){
coordTempStart = (Coordinata) pathIterator.next();
}
if(pathIterator.hasNext()){
coordTempArrival = (Coordinata) pathIterator.next();
animation = new TranslateAnimation(coordTempStart.getX(),
coordTempArrival.getX(),
coordTempStart.getY(),
coordTempArrival.getY());
animation.setDuration(3000);
image.startAnimation(animation);
}
while(pathIterator.hasNext()){
coordTempStart=coordTempArrival;
coordTempArrival = (Coordinata) pathIterator.next();
animation.setAnimationListener(new TranslateAnimation.AnimationListener(){
public void onAnimationStart(Animation arg0) {}
public void onAnimationRepeat(Animation arg0) {}
public void onAnimationEnd(Animation arg0) {
animation = new TranslateAnimation(coordTempStart.getX(),
coordTempArrival.getX(),
coordTempStart.getY(),
coordTempArrival.getY());
animation.setDuration(3000);
image.startAnimation(animation);
}
});
}
I suggest to use ObjectAnimator and AnimatorSet to animate views. Object animator is available only for api > 11 but you can use NineOldAndroid if you have to keep the compatibility.
your code will be something like this (in pseudocode):
...
AnimatorSet animatorSet = new AnimatorSet();
while(pathIterator.hasNext()){
...
//Set _your_delta_x_ and _your_delta_y_ from iterator
...
ObjectAnimator xTrasnlationObjectAnimator = ObjectAnimator.ofFloat(v, view_x, _your_delta_x_);
ObjectAnimator yTrasnlationObjectAnimator = ObjectAnimator.ofFloat(v, view_y, _your_delta_y_);
animatorSet.playSequentially(xTrasnlationObjectAnimator, yTrasnlationObjectAnimator);
}
...
animatorSet.start()
to set right parameters to object animator refer the official documentation http://developer.android.com/reference/android/animation/ObjectAnimator.html
Just for the sake of completeness, i publish the actual code used to solve the problem:
// in this list you can insert as many animations you want
List<Animator> animations = new ArrayList<Animator>();
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator xTrasnlationObjectAnimator = ObjectAnimator.ofFloat(image, View.TRANSLATION_X, (float)300);
xTrasnlationObjectAnimator.setRepeatCount(0);
ObjectAnimator yTrasnlationObjectAnimator = ObjectAnimator.ofFloat(image, View.TRANSLATION_Y, (float)300);
yTrasnlationObjectAnimator.setRepeatCount(0);
ObjectAnimator x2TrasnlationObjectAnimator = ObjectAnimator.ofFloat(image, View.TRANSLATION_X, (float)400);
x2TrasnlationObjectAnimator.setRepeatCount(0);
animations.add(xTrasnlationObjectAnimator);
animations.add(yTrasnlationObjectAnimator);
animations.add(x2TrasnlationObjectAnimator);
animatorSet.playSequentially(animations);
animatorSet.start();