Android展开/折叠RelativeLayout

Posted

技术标签:

【中文标题】Android展开/折叠RelativeLayout【英文标题】:Android expand/collapse RelativeLayout 【发布时间】:2017-04-09 07:14:20 【问题描述】:

我尝试了该主题的各种解决方案(请参阅。android: Expand/collapse animation),但没有一个真正适合我。我敢肯定,投票最多的是好的,它不起作用的原因是我不明白一些东西。请告诉我我做错了什么。提前谢谢你:)

编辑:我的问题的要点是,当我点击元素“relativeZaplon”时,它展开得很好,但是当我想折叠它时,它却不对应。 p>

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_
    android:layout_
    android:orientation="vertical">

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

【问题讨论】:

您能否更具体地说明什么不起作用?你有错误吗? @AHoneyBustard 嗨,是的,我很抱歉。我已经编辑了帖子 :) 干杯。 【参考方案1】:

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

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

【讨论】:

【参考方案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。

【讨论】:

非常感谢。我觉得自己像个假人,我没看到。此解决方案解决了问题。【参考方案3】:

我将解释我选择动画布局更改的方式。

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

您可以根据需要更改fromX,toX,fromY & toY

例如,如果显示视图并且您必须将其展开,则根据需要将fromXfromY设置为1.0ftoXtoY

现在,使用同一个类,您可以通过稍微扩展视图然后将其缩小到原始大小来创建更酷的显示视图效果。为此,将使用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);

【讨论】:

以上是关于Android展开/折叠RelativeLayout的主要内容,如果未能解决你的问题,请参考以下文章

Android展开/折叠RelativeLayout

如何检查组是不是在 Android ExpandableListView 中展开或折叠?

带有展开和折叠功能的 Android 视频视图

将动画添加到 ListView 以展开/折叠内容

如何在 Android 上实现 Material Design 展开/折叠列表?

FlutterAndroidFlutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )