Search code examples
androidlayoutandroid-animation

Android expand/collapse RelativeLayout


I've tried various solutions from this topic (see. Android: Expand/collapse animation ) and none of them really worked for me. I'm sure that the most voted ones are good and the reason that it won't work is that I don't understand something.

The main point of my problem is, that when I click on the element 'relativeZaplon' it expands very well, yet when I want to collapse it, it does not correspond.

MainActivity

 public class MainActivity extends AppCompatActivity {

    private boolean isVisible = false;
    private RelativeLayout mRelativeZaplon;
    private RelativeLayout mRelativeToSlide;
    private ExpandOrCollapse mAnimationManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mAnimationManager = new ExpandOrCollapse();
        mRelativeZaplon = (RelativeLayout) findViewById(R.id.relativeZaplon);
        mRelativeToSlide = (RelativeLayout) findViewById(R.id.relativevToSlide);
        mRelativeZaplon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isVisible) {
                    mAnimationManager.collapse(mRelativeToSlide, 1000, 200);
                    isVisible = false;
                } else if (!isVisible){
                    mAnimationManager.expand(mRelativeToSlide, 1000, 200);
                    isVisible = true;
                }
            }
        });
    }
}

Expand/Collapse Class

    public class ExpandOrCollapse {

    public static void expand(final View v, int duration, int targetHeight) {
        int prevHeight  = v.getHeight();
        v.setVisibility(View.VISIBLE);
        ValueAnimator valueAnimator = ValueAnimator.ofInt(prevHeight, targetHeight);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                v.getLayoutParams().height = (int) animation.getAnimatedValue();
                v.requestLayout();
            }
        });
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.setDuration(duration);
        valueAnimator.start();
    }

    public static void collapse(final View v, int duration, int targetHeight) {
        int prevHeight  = v.getHeight();
        ValueAnimator valueAnimator = ValueAnimator.ofInt(prevHeight, targetHeight);
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                v.getLayoutParams().height = (int) animation.getAnimatedValue();
                v.requestLayout();
            }
        });
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.setDuration(duration);
        valueAnimator.start();
    }
}

XML

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:background="@color/colorPrimaryDark"
        android:id="@+id/relativevToSlide"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone">
    </RelativeLayout>
    <RelativeLayout
        android:id="@+id/relativeZaplon"
        android:background="@color/colorAccent"
        android:layout_width="match_parent"
        android:layout_height="20dp"
        android:layout_below="@+id/relativevToSlide"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true">
    </RelativeLayout>
</LinearLayout>

Solution

  • It is because

                if (isVisible) {
                    mAnimationManager.collapse(mRelativeToSlide, 1000, 200);
                    isVisible = false;
                } else if (!isVisible){
                    mAnimationManager.expand(mRelativeToSlide, 1000, 200);
                    isVisible = true;
                }
    

    collapse() and expand() do the same thing, they are both expand Animations in this case. You need to pass a different value to your collapse() method; The simple solution is

        mAnimationManager.collapse(mRelativeToSlide, 1000, -200);
    

    But there are some more issues with your coding style, for example you could just get rid of your collapse() method because calling expand two times like this would also work :

                if (isVisible) {
                    mAnimationManager.expand(mRelativeToSlide, 1000, -200);
                    isVisible = false;
                } else if (!isVisible){
                    mAnimationManager.expand(mRelativeToSlide, 1000, 200);
                    isVisible = true;
                }
    

    I suggest you post it on Code Review.