Apply one animation to multiple views at the same time
Asked Answered
R

3

25

So Id like to rotate a handful of views all at the same time, all using the same rotation specs. The issue is that for some reason the rotation acts differently for the second element. Apparently this has to do with the animation object actually changing state in between those two lines of code. Obviously I could just create a seperate Animation object and apply it, but I feel like there is an easier way (I have about 15 views)

Rotates only the first view correctly:

Animation rotateAnim = AnimationUtils.loadAnimation(this, R.anim.rotationtoportrait);
target.startAnimation(rotateAnim);
lightBtn.startAnimation(rotateAnim);

Rotates both correctly

Animation rotateAnim = AnimationUtils.loadAnimation(this, R.anim.rotationtoportrait);
Animation rotateAnim2 = AnimationUtils.loadAnimation(this, R.anim.rotationtoportrait);
target.startAnimation(rotateAnim);
lightBtn.startAnimation(rotateAnim2);

XML:

<?xml version="1.0" encoding="utf-8"?>
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="-90"
    android:toDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="500" android:fillAfter="true">

Anyone have any ideas?

Rooseveltroost answered 12/2, 2013 at 20:57 Comment(4)
Try to use the new Animation API (for backwards compatability use NineOldAndroids). Also I recommend to watch this: youtube.com/watch?v=_UWXqFBF86UFlashy
Love the video! But what new API, as far as I can tell this is what the guy in the video did?(towards the end at least)Rooseveltroost
Wrong video, sorry. ;) youtube.com/watch?v=3UbJhmkeSigFlashy
Thanks for the videos. The new API is definitely more powerful, but I think either way you need to create a 1-to-1 relationship of animator objects to things you want to rotate. Unless you can set multiple target views with anim.setTarget(v1) anim.setTarget(v2)?Rooseveltroost
R
5

So I guess this just isn't possible, so I created a helper method to just apply the same animation to a list of views:

public void doRotations(ArrayList<View> views, int start, int end, int xprop, float xscale, int yprop, float yscale, int duration, Boolean fillAfter){

    for(int i = 0; i < views.size(); i++){
        RotateAnimation temp = new RotateAnimation(start, end, xprop, xscale, yprop, yscale);
        temp.setDuration(duration);
        temp.setFillAfter(fillAfter);
        views.get(i).startAnimation(temp);
    }
}

Definitely a hack, but I guess thats all I'm able to do right now

Rooseveltroost answered 12/2, 2013 at 21:48 Comment(2)
This indeed runs the animation in parallel, BUT you can see a slight delay beteen the animations if you look closely (since you are triggering the animations squentially after all).Doublecross
@Doublecross If you're doing this on the main thread, nothing will be drawn until you're done. Your calculations block the main thread. No animations will start immediately. When you're done, the next layout pass will actually start the animations, and I believe they should start at the same time.Sprinkle
F
10

Do it like this:

ObjectAnimator anim = ObjectAnimator.ofFloat(view, "y", 100f);
arrayListObjectAnimators.add(anim);

ObjectAnimator anim1 = ObjectAnimator.ofFloat(view, "x", 0f);
arrayListObjectAnimators.add(anim1);

ObjectAnimator[] objectAnimators = arrayListObjectAnimators.toArray(new ObjectAnimator[arrayListObjectAnimators.size()]);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(objectAnimators);
animSetXY.duration(1000);
animSetXY.start();
Flashy answered 12/2, 2013 at 21:55 Comment(2)
This does not answer the question, If I am correct you are applying 2 animations to the same view. The original post wants to apply the same animation to 2 viewsAntirrhinum
.duration(1000) should be .setDuration(1000)Lardaceous
R
5

So I guess this just isn't possible, so I created a helper method to just apply the same animation to a list of views:

public void doRotations(ArrayList<View> views, int start, int end, int xprop, float xscale, int yprop, float yscale, int duration, Boolean fillAfter){

    for(int i = 0; i < views.size(); i++){
        RotateAnimation temp = new RotateAnimation(start, end, xprop, xscale, yprop, yscale);
        temp.setDuration(duration);
        temp.setFillAfter(fillAfter);
        views.get(i).startAnimation(temp);
    }
}

Definitely a hack, but I guess thats all I'm able to do right now

Rooseveltroost answered 12/2, 2013 at 21:48 Comment(2)
This indeed runs the animation in parallel, BUT you can see a slight delay beteen the animations if you look closely (since you are triggering the animations squentially after all).Doublecross
@Doublecross If you're doing this on the main thread, nothing will be drawn until you're done. Your calculations block the main thread. No animations will start immediately. When you're done, the next layout pass will actually start the animations, and I believe they should start at the same time.Sprinkle
H
0

I was able to do this in Kotlin by programmatically creating one AnimatorSet.
1. Create an ArrayList of the views you want to animate

 var viewList = arrayListOf(view1,view2,view3)

2. Loop through the ArrayList and create a growing AnimatorSet

var ix = 0
var anim = AnimatorSet()
var viewList = arrayListOf(view1,view2,view3)
        viewList.forEach{
        // Initiate the animator set with one ObjectAnimator
            if(ix == 0){
                anim = AnimatorSet().apply {
                    play(ObjectAnimator.ofFloat(it, "rotation", 0F, 360F))
                }
            }
        // Add one ObjectAnimator at a time to the growing AnimatorSet
            else{
                var currentAnim = ObjectAnimator.ofFloat(it,"rotation",0F,360F)
                anim = AnimatorSet().apply {
                    play(anim).with(currentAnim)
                }
            }
            ix++
        }

3. Start the animation

button.setOnClickListener {
            AnimatorSet().apply {
                play(anim)
                start()
            }
Houseboat answered 29/5, 2020 at 3:55 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.