Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LayoutTransition for LinearLayout with wrap_content

I'm trying to animate the add/remove actions of the views of an LinearLayout that has it's height set as wrap_content.

Currently I've tried setting android:animateLayoutChanges="true" for the LinearLayout and programmatically enabling the transitions like this:

LayoutTransition transition = new LayoutTransition();
transition.setDuration(300);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    transition.enableTransitionType(LayoutTransition.APPEARING);
    transition.enableTransitionType(LayoutTransition.DISAPPEARING);
    transition.setAnimateParentHierarchy(true);
}

container.setLayoutTransition(transition); 

The Appearing seems to work very smooth and it animates and resizes as I want.

The issue I'm having is with Disappearing as the LinearLayout container is resized before the remove animation is finished.

I've also tried playing around with the setAnimateParentHierarchy() and it doesn't seem to really affect on how and when the resize of the container is done.

like image 794
Ionut Negru Avatar asked Nov 09 '22 17:11

Ionut Negru


1 Answers

A simple solution is to set a layout transition to the first ancestor which does not use wrap_content.

The following code finds the correct anscestor, sets the required animation and restore the original LayoutTransition (if any existed) at the end of the animation.

Call this method in your code where you perform the add/remove actions. None of your code which is included in the question is required.

Note: This solution will only work for SDK >= JELLY_BEAN.

private static void setHeightChangeAnimation(ViewGroup animatedLayout) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        ViewGroup vg = animatedLayout;
        while (vg instanceof ViewGroup) {
            vg = (ViewGroup) vg.getParent();
            if (vg instanceof ViewGroup  && vg.getLayoutParams().height != LayoutParams.WRAP_CONTENT) {
                LayoutTransition animatedLayoutLt = animatedLayout.getLayoutTransition();
                LayoutTransition lt = new LayoutTransition();
                lt.enableTransitionType(LayoutTransition.CHANGING);
                lt.setDuration(animatedLayoutLt.getDuration(LayoutTransition.CHANGE_APPEARING));
                lt.setStartDelay(LayoutTransition.CHANGING, animatedLayoutLt.getStartDelay(LayoutTransition.APPEARING));

                final ViewGroup finalVg = vg;
                final LayoutTransition oldLt = finalVg.getLayoutTransition();
                lt.addTransitionListener(new LayoutTransition.TransitionListener() {
                    public void startTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {}

                    public void endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
                        finalVg.setLayoutTransition(oldLt);
                    }
                });
                finalVg.setLayoutTransition(lt);

                break;
            }
        }
    }
}

And use this to call:

    setHeightChangeAnimation(yourAnimatedLinearLayout);
like image 88
OferR Avatar answered Nov 14 '22 23:11

OferR