Android展开/折叠RelativeLayout

时间:2016-11-24 23:09:05

标签: android layout android-animation collapse

我尝试过这个主题的各种解决方案(参见。Android: Expand/collapse animation),但这些解决方案对我来说都没有。我确信投票最多的是好的,它不起作用的原因是我不明白。请告诉我我做错了什么。提前谢谢你:)

编辑:我的问题的主要问题是,当我点击元素'relativeZaplon'时它会很好地展开,但是当我想要折叠它时,它就不对应。

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;
                }
            }
        });
    }
}

展开/折叠类

    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>

3 个答案:

答案 0 :(得分:4)

这是我的方法版本,你不必设置任何高度,它会根据其可见性展开或折叠任何视图。

public static void expand(final View v, int duration) {
    final boolean expand = v.getVisibility()!=View.VISIBLE;

    int prevHeight  = v.getHeight();
    int height = 0;
    if (expand) {
        int measureSpecParams = View.MeasureSpec.getSize(View.MeasureSpec.UNSPECIFIED);
        v.measure(measureSpecParams, measureSpecParams);
        height = v.getMeasuredHeight();
    }

    ValueAnimator valueAnimator = ValueAnimator.ofInt(prevHeight, height);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            v.getLayoutParams().height = (int) animation.getAnimatedValue();
            v.requestLayout();
        }
    });

    valueAnimator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            if (expand){
                v.setVisibility(View.VISIBLE);
            }
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            if (!expand){
                v.setVisibility(View.INVISIBLE);
            }
        }

        @Override
        public void onAnimationCancel(Animator animation) {

        }

        @Override
        public void onAnimationRepeat(Animator animation) {

        }
    });
    valueAnimator.setInterpolator(new DecelerateInterpolator());
    valueAnimator.setDuration(duration);
    valueAnimator.start();
}

只需调用这样的方法:

expand(YOURVIEWID,500);

答案 1 :(得分:1)

这是因为

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

collapse()和expand()做同样的事情,在这种情况下它们都是扩展动画。您需要将不同的值传递给collapse()方法; 简单的解决方案是

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

但是你的编码风格还有一些问题,比如你可以摆脱你的collapse()方法,因为这样调用expand两次也会有效:

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

我建议你在Code Review发布。

答案 2 :(得分:0)

我将说明选择动画布局更改的方式。

Android有一个名为ScaleAnimation的特殊动画类,借助它我们可以顺利地扩展或折叠视图。

通过对角扩展显示视图:

ScaleAnimation expand = new ScaleAnimation(
   0, 1.0f,
   0, 1.0f,
Animation.RELATIVE_TO_PARENT, 0,
Animation.RELATIVE_TO_PARENT, 0);
expand.setDuration(250);

view.startAnimation(expand)

使用的构造函数为:

ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

因此您可以相应地更改值。

例如,以下示例将水平显示视图动画

ScaleAnimation expand = new ScaleAnimation(
   0, 1.1f,
   1f, 1f,
   Animation.RELATIVE_TO_PARENT, 0,
   Animation.RELATIVE_TO_PARENT, 0);
expand.setDuration(250);

您可以根据需要更改fromXtoXfromYtoY

例如,如果显示了视图,而您只需要展开它,则将fromXfromY放在1.0f上,将toXtoY放在需要。

现在,使用相同的类,您可以通过将视图稍微扩大一点,然后将其缩小到原始大小,来创建更酷的效果来显示视图。为此,将使用AnimationSet。这样会产生一种泡沫效果。

下面的示例用于创建气泡效果以显示视图:

AnimationSet expandAndShrink = new AnimationSet(true);
ScaleAnimation expand = new ScaleAnimation(
   0, 1.1f,
   0, 1.1f,
Animation.RELATIVE_TO_PARENT, 0,
Animation.RELATIVE_TO_PARENT, 0);
expand.setDuration(250);

ScaleAnimation shrink = new ScaleAnimation(
   1.1f, 1f,
   1.1f, 1f,
Animation.RELATIVE_TO_PARENT, 0,
Animation.RELATIVE_TO_PARENT, 0);
shrink.setStartOffset(250);
shrink.setDuration(120);

expandAndShrink.addAnimation(expand);
expandAndShrink.addAnimation(shrink);
expandAndShrink.setFillAfter(true);
expandAndShrink.setInterpolator(new AccelerateInterpolator(1.0f));

view.startAnimation(expandAndShrink);