【问题标题】:View Animations in Android Collapse/Expand Views in LinearLayout在 Android 中查看动画 在 LinearLayout 中折叠/展开视图
【发布时间】:2016-10-28 09:43:51
【问题描述】:

我将图像视图动态添加到我的线性布局中,

我要实现

这是我所做的示例代码

MainActivity

 package ksp.com.animationssample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    private Button btn_expand;
    private Button btn_collapse;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_expand = (Button) findViewById(R.id.btn_expand);
        btn_collapse = (Button) findViewById(R.id.btn_collapse);
        LinearLayout.LayoutParams vp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        final LinearLayout layout = (LinearLayout) findViewById(R.id.imageLayout);


        for (int i = 0; i < 3; i++) {
            final ImageView image = new ImageView(MainActivity.this);
            image.setLayoutParams(vp);
            if (i == 0)
                image.setImageDrawable(getResources().getDrawable(R.drawable.item_image1));
            else image.setImageDrawable(getResources().getDrawable(R.drawable.item_image2));
            if (i == 2)
                image.setVisibility(View.VISIBLE);
            else
                image.setVisibility(View.GONE);
            layout.addView(image);
        }


        btn_expand.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                expandOrCollapse(layout.getChildAt(2), true, layout.getChildAt(0).getHeight() + layout.getChildAt(1).getHeight());
                expandOrCollapse(layout.getChildAt(1), true, layout.getChildAt(0).getHeight());
                expandOrCollapse(layout.getChildAt(0), true, 0);


            }
        });
        btn_collapse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                expandOrCollapse(layout.getChildAt(0), false, 0);
                expandOrCollapse(layout.getChildAt(1), false, layout.getChildAt(0).getHeight());
                expandOrCollapse(layout.getChildAt(2), false, layout.getChildAt(0).getHeight() + layout.getChildAt(1).getHeight());
            }
        });


    }


    public void expandOrCollapse(final View v, boolean is_expand, final int animheight) {
        TranslateAnimation anim = null;
        if (is_expand) {
            anim = new TranslateAnimation(0.0f, 0.0f, -animheight, 0.0f);
            v.setVisibility(View.VISIBLE);
            Animation.AnimationListener expandedlistener = new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {


                }
            };

            anim.setAnimationListener(expandedlistener);
        } else {
            anim = new TranslateAnimation(0.0f, 0.0f, 0.0f, -animheight);
            Animation.AnimationListener collapselistener = new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    v.setVisibility(View.GONE);
                }
            };

            anim.setAnimationListener(collapselistener);
        }

        anim.setDuration(1500);
        anim.setInterpolator(new AccelerateInterpolator(0.5f));
        v.startAnimation(anim);
    }
}

activity_mainn.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:background="@android:color/holo_blue_dark"
    tools:context="ksp.com.animationssample.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:id="@+id/btn_expand"
        android:text="Expand"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn_collapse"
        android:text="Collopse"/>
<ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scrollbars="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:id="@+id/imageLayout"
        android:gravity="center"

        android:orientation="vertical"
        android:layout_height="wrap_content">
    </LinearLayout>
    <!--android:animateLayoutChanges="true"-->
</ScrollView>


</RelativeLayout>

当我第一次点击 expand 按钮时,从第二次开始就没有显示动画了。

启用点击折叠按钮后显示项目。

下一步做什么: 当我选择任何视图项目时,它必须显示选择动画然后折叠动画,折叠后它必须显示为顶部视图,就像我在上面的图片中提到的那样。目前我正在硬编码视图的数量,并为每个视图编写静态动画,并使用动画的静态高度,即 (expandOrCollapse(view, height_of_view))

我为此搜索了一段时间,但没有运气。

我关注Vie expand/collapsesmooth expand / collapse ,但他们无法帮助我展开线性布局中的所有视图。

我们可以这样做列表视图是回收器视图还是什么?

为了节省时间,我已将我的示例添加到 git hub 你可以试试Animation Sample Github

请给我建议。

【问题讨论】:

  • 只是为了明确问题 - 您希望底部的信用卡在折叠后保持可见?还是有其他问题?
  • 假设当我点击第二张卡片时它必须在折叠后出现在顶部
  • CardStackView 是一个不错的库,考虑访问一次,github.com/loopeer/CardStackView
  • @NougatLover 感谢您的 git 链接。我非常具体地实现这个动画感谢您的帮助。

标签: android android-animation android-linearlayout


【解决方案1】:

我为它做了单独的课程。检查它是否适合您:

public class DropDownAnim extends Animation {
    private final int sourceHeight;
    private final int targetHeight;
    private final View view;
    private final boolean down;

    public DropDownAnim(View view, int sourceHeight, int targetHeight, boolean down) {
        this.view = view;
        this.sourceHeight = sourceHeight;
        this.targetHeight = targetHeight;
        this.down = down;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        int newHeight;
        if (down) {
            newHeight = sourceHeight + (int) (targetHeight * interpolatedTime);
        } else {
            newHeight = sourceHeight + targetHeight - (int) (targetHeight * interpolatedTime);//(int) (targetHeight * (1 - interpolatedTime));
        }
        view.getLayoutParams().height = newHeight;
        view.requestLayout();
        view.setVisibility(down ? View.VISIBLE : View.GONE);
    }

    @Override
    public void initialize(int width, int height, int parentWidth,
            int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
}

在处理这个问题时。展开

public void expand(final View v) {
        final int sourceHeight = v.getLayoutParams().height;
        final int targetHeight = getResources().getDimensionPixelSize(R.dimen.notification_height);//v.getMeasuredHeight();
        DropDownAnim a = new DropDownAnim(v,targetHeight,true);
        a.setDuration((int) (targetHeight / v.getContext().getResources().getDisplayMetrics().density));
        a.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                // Your code on end of animation
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        v.setVisibility(View.INVISIBLE);
        v.startAnimation(a);
    }

对于折叠:

public void collapse(final View v) {
        final int sourceHeight = v.getLayoutParams().height;
        final int targetHeight = v.getMeasuredHeight();
        DropDownAnim a = new DropDownAnim(v, targetHeight, false);
        a.setDuration((int) (targetHeight / v.getContext().getResources().getDisplayMetrics().density));
        a.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                // Your code on end of animation
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        v.startAnimation(a);
    }

更新:
添加sourceHeight 以防止视图闪烁。

【讨论】:

  • 感谢您的全面解决,我将这些方法应用于我的视图,例如 'expand(layout.getChildAt(2));展开(布局。getChildAt(1));展开(layout.getChildAt(0)); ' 似乎它的作品。此代码如何适用于动态添加的布局?我们可以使用 for 循环吗?
  • 是的,你可以使用循环
  • 在研究了您的代码后,我将您的代码放到了我的项目中,但我的观点只是眨眼就消失了。你能多帮助一点这段代码是如何工作的吗?我申请了线性布局中的每个视图。还有它是如何知道动画高度的?
  • 动画高度 = 直到你想要扩展它的高度。就我而言,我在dimens.xml 中定义了高度。即使你可以得到高度。就像您希望第二个视图滑动到第一个视图高度 + 第二个视图高度一样。所以这就是你的身高。同样,对于第 3 = 第 1 高度 + 第 2 高度 + 第 3 高度。并对所有这些视图进行动画处理,并在它们之间留出一些空隙,以获得动画的真实感受
  • 毕竟替换并尝试你的代码它不能作为动画工作。我的Linear Layout只是闪入闪出,我尝试修改动画的时间间隔没有运气。
【解决方案2】:

尽量不要隐藏您的目标视图(现在您在折叠动画结束后为所有视图设置可见性 GONE)并执行以下操作:

targetView.bringToFront();
targetView.invalidate();
targetView.getParent().requestLayout();

【讨论】:

  • 感谢 'v.bringToFront()' 方法我将使用该更改更新我的存储库,但是如果视图是动态的,即从服务器计数,我们如何处理。在这里,我分别为每个视图编写了动画,这不是正确的方式吗?你能建议我为多视图处理这种类型的动画的更好方法吗?您还可以看到列表中应该有选择视图的选择动画。我们该如何处理呢?感谢您的帮助
  • 我想,你可以在 for 循环中应用动画。对于选择动画 - 你说什么样的动画?在 onClick 回调中,我们获取目标视图并可以应用任何类型的动画,甚至可以在 xml 布局中设置动画。我想你没有太多动画项目,所以使用 FrameLayout 作为容器(不是 ListView)就足够了
  • @kathi 你可以附上代码以供学习:)。我真的不知道你如何处理这个问题:(
  • @udayatom 请在我的 github 示例中找到代码 github.com/kathisai/AnimationsSample
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-09
  • 1970-01-01
  • 2015-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多