Android展开/折叠RelativeLayout

问题描述 投票:4回答:3

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

编辑:我的问题的主要问题是,当我点击元素'relativeZaplon'时它扩展得非常好,但是当我想要折叠它时,它就不对应了。

我的知识

 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>
android layout android-animation collapse
3个回答
2
投票

这是因为

            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上。


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

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);
© www.soinside.com 2019 - 2024. All rights reserved.