p.j.rudnicki p.j.rudnicki - 9 days ago 6
Android Question

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. Please tell me what i'm doing wrong. Thank you in advance :)

EDIT: 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>

Answer

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.

Comments