Android:LinearLayout滑动屏幕动画

时间:2017-09-08 23:57:13

标签: android android-layout animation

我在垂直LinearLayout(父级)中有两个布局(绿色在顶部,红色在底部),看起来与此类似:

当焦点从绿色变为红色时,我希望绿色从屏幕上滑下并让红色同时向上滑动并填满整个屏幕。当焦点从红色向上移动时,我希望绿色滑回屏幕并返回到原始配置。我试过看了很多其他的问题,但没有人有我需要的解决方案。我尝试改变去掉和可见之间的可见性,但我希望它是一个平滑的动画。我尝试在外部LinearLayout上使用parentLayout.animate().translationY(greenLayout.getHeight())并确实提供了我想要的动画但是红色不会扩展以填充屏幕,如下所示:

我知道这个问题与this one相似,但这个问题真的很陈旧,只有一个答案对我不起作用。

1 个答案:

答案 0 :(得分:0)

我的解决方案有很多不同的部分,所以我将从完整的XML和Java代码开始,然后讨论重要的部分:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <View
        android:id="@+id/green"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#0f0" />

    <View
        android:id="@+id/red"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#f00"/>

</LinearLayout>

在XML中,唯一非常重要的部分是红色视图使用0dp的高度和1的权重。这意味着它占用了所有额外的垂直空间,这在我们摆脱绿色视图时非常重要。

public class MainActivity extends AppCompatActivity {

    private int originalHeight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final View green = findViewById(R.id.green);
        final View red = findViewById(R.id.red);

        green.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                green.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                originalHeight = green.getHeight();
            }
        });

        green.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                animateHeightOfView(green, originalHeight, 0);
            }
        });

        red.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                animateHeightOfView(green, 0, originalHeight);
            }
        });
    }

    private void animateHeightOfView(final View view, int start, int end) {
        ValueAnimator animator = ValueAnimator.ofInt(start, end);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                int height = (int) valueAnimator.getAnimatedValue();
                ViewGroup.LayoutParams params = view.getLayoutParams();
                params.height = height;
                view.setLayoutParams(params);
            }
        });
        animator.start();
    }
}

在Java中,两个主要部分是ViewTreeObserver.OnGlobalLayoutListeneranimateHeightOfView()方法。

OnGlobalLayoutListener存在以捕获绿色视图的原始高度。我们必须使用侦听器才能执行此操作,而不是仅在originalHeight = green.getHeight()内编写onCreate(),因为此时绿色视图实际上并未布局,因此getHeight()将返回0如果我们尝试过的话。

animateHeightOfView()方法利用ValueAnimator类为您传递给它的任何视图的高度设置动画。由于视图的高度没有直接的设置器,我们不能使用更简单的方法,如.animate()。我们设置ValueAnimator以在每个帧上生成int值,然后我们使用ValueAnimator.AnimatorUpdateListener修改视图的LayoutParams来设置高度。

随意玩它。我正在使用点击监听器来触发动画,你提到了焦点,但如果它适合你,你应该能够以不同的方式调用animateHeightOfView()

enter image description here enter image description here