Android扩展/折叠RelativeLayout

7
我尝试了这个主题中的各种解决方案(参见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>

你能更具体地说明哪里出了问题吗?你是否收到了错误提示? - A Honey Bustard
@AHoneyBustard 嗨,是的,抱歉。我已经编辑了帖子:) 干杯。 - pjrki
3个回答

7

这是我的方法版本,您无需设置任何高度,它会根据视图的可见性来展开或折叠。

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

3
由于
            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;
            }

我建议你将其发布在代码审查上。


非常感谢。我感觉自己像个傻瓜,没看到那个。这个解决方案解决了问题。 - pjrki

1
我会解释我选择的布局动画方式。
Android有一个特殊的Animation类名为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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接