Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can LayoutAnimationController animate only specified Views

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.

like image 738
happydude Avatar asked Feb 20 '23 00:02

happydude


2 Answers

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.

like image 80
happydude Avatar answered Feb 27 '23 10:02

happydude


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()
}
like image 28
Josttie Avatar answered Feb 27 '23 09:02

Josttie