4

Is it possible to override Android's LayoutAnimationController in such a way that only certain child Views that I specify inside a ViewGroup will animate? My goal is to choose an arbitrary set of the child views based on the current state of the Activity and animate them with the same animation at exactly the same time, then at a later time choose a different arbitrary set of child views and do the same thing. I would like to be able to do this continually until the Activity is finished running.

So far I have looked at and dismissed a couple of options:

  1. Calling startAnimation(Animation) the specific child views individually, however there is not a guarantee that they will all start and end at exactly the same time, especially if the number of views in the arbitrary set is large.
  2. Overriding LayoutAnimationController.getAnimationForView() seemed like it would be the easiest way, but the method is final and cannot be overridden.

I have been scratching my head for some time on this and figured I would give Stack Overflow a shot.

happydude
  • 3,869
  • 2
  • 23
  • 41

3 Answers3

7

I wasn't able to find a way to change Android's LayoutAnimationController, but did come up with a simple solution that does what I want. I created a View subclass that can selectively ignore calls to run an animation if I so choose.

public class AnimationAverseView extends View {

    private boolean mIsAnimatable = true;

    public void setAnimatible(boolean isAnimatable) {
        if (!isAnimatable) {
            clearAnimation();
        }
        mIsAnimatable = isAnimatable;
    }

    @Override
    public void startAnimation(Animation animation) {
        if (mIsAnimatable) {
            super.startAnimation(animation);
        }
    }
}

I did not worry about any other possible animation-related methods, since I only animate the Views via a LayoutAnimationController.

happydude
  • 3,869
  • 2
  • 23
  • 41
  • Hey this solution is not working....please help me, i have set the mIsAnimatable of few childs but still all are animating – Shridutt Kothari Jun 12 '13 at 14:42
  • Are you trying to animate these views using anything other than a LayoutAnimationController? There are other animation-related methods that can be called on the view which are not handled by the above code. – happydude Jul 05 '13 at 19:33
  • If the views you have, which you don't want to be affected, are inflated from an xml, and is in a viewGroup such as RelativeLayout, you could instead create AnimationAverseRelativeLayout and use that in your layout. This helped me in a listView setting, where I needed some cells to animate, and some to not animate. – havchr Aug 22 '13 at 14:38
  • @havchr Did you have to do anything else to get the AnimationAverseLayout to work within your ListView? I am trying to do this with a LinearLayout that I set to be my header in the listview and this method does not seem to work – GrouchyPanda Feb 12 '14 at 23:46
  • @ChrisM did you create AnimationAverseLinearLayout class and use that instead of linearLayout? If you did, I'm not sure what is not working. – havchr Feb 13 '14 at 15:28
  • @ChrisM I'm not sure if this is your issue, but having an "animation averse" ViewGroup does not prevent any of its child views from animating if startAnimation() is called on them directly. In that case, you would need to tell each child not to animate individually. – happydude Feb 17 '14 at 17:58
1

I see this question was asked 7 years and 6 months ago, but today I have encountered it myself and creating custom child views seems a bit cumbersome to me.

I found that using a custom outer layout seems to do the trick, where you have to override the attachLayoutAnimationParameters. This method is called for every child view that is part of a layout animation, and it is called when the layout animation is actually triggered within the ViewGroup. It is attaching AnimationLayoutParams to the child, in which case it is animated. So simply said, if you do not attach any LayoutAnimation Parameters to a child, it will not be part of the layout animation.

class CustomLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {

    private val excludeForLayoutAnimation by lazy {
        listOfNotNull(findViewById(R.id.text), findViewById(R.id.fab))
    }

    override fun attachLayoutAnimationParameters(
        child: View?,
        params: ViewGroup.LayoutParams?,
        index: Int,
        count: Int
    ) {
        if (child !in excludeForLayoutAnimation) {
            super.attachLayoutAnimationParameters(child, params, index, count)
        }
    }

}

If you now simply call this on your outer custom view, it will exclude the children that you specify:

customView?.apply {
    layoutAnimation = AnimationUtils.loadLayoutAnimation(
        context,
        R.anim.layout_animation_fade_in
    )
    scheduleLayoutAnimation() // or maybe startLayoutAnimation()
}
Josttie
  • 250
  • 2
  • 7
0

I cannot add a comment to the accepted answer, so adding some additional information here. The comment from happydude (Feb 17) was correct for me as well. I had a FrameLayout as the outermost View for my ListView header, and I needed to override the setAnimation() method to prevent the header from being animated with the rest of the list. So you should check out which other animation methods you might need to override.

Irshad
  • 3,071
  • 5
  • 30
  • 51