为View添加平滑隐藏/显示动画,为空白空间填充第二个视图

时间:2014-11-03 22:41:53

标签: android android-animation

我正在尝试动画视图并在某些DP滚动后隐藏它并且我使一切都很好,但问题是当你在应该触发的Y值之前或之后缓慢滚动时它会非常轻弹动画。

我觉得这个电影是因为我必须将其可见性设置为Gone并将其他视图更新为match_parent,它只适用于TraslationY:

           view.animate()
                    .translationY(-view.getBottom())
                    .alpha(0)
                    .setDuration(HEADER_HIDE_ANIM_DURATION)
                    .setInterpolator(new DecelerateInterpolator());

我尝试将布局设置为relative,将View 2设置为match_parent以查看是否可以避免可见性更改但是它不起作用...

我已经实施了Google I / O 2014 BaseActivity.java文件中的所有必需代码: https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/BaseActivity.java#L17

动画有效...但我认为,由于我的自定义视图不是具有叠加属性的操作栏,因此自定义视图不会离开,下面的LinearLayout将不会填充空白区域(没有)。

所以,我使用动画侦测器并设置自定义视图可见性在动画结束时消失但当你接近触发动画的预期Y点时它将以可怕的方式轻弹(轻弹为自定义视图可见性已消失,下面的LinearLayout需要调整自身大小以填充空白区域,如果你在那里慢慢滚动,它会很快重复。)

XML:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"


    android:clickable="false"
    android:animateLayoutChanges="true">

    <com.project.app.layouts.TabsLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
/>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/tabs">
    <FrameLayout
        android:id="@+id/content_frame_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1"
        android:background="@android:color/white"/>
    </LinearLayout>

</RelativeLayout>

当它不是动作栏时,有没有办法做到这一点?

编辑: 添加了关于当你在触发动画隐藏/显示的Y点周围慢慢滚动时如何轻弹的评论。

3 个答案:

答案 0 :(得分:1)

我建议你使用android:hardwareAccelerated =&#34; true&#34;您的清单文件中的属性。它将使用您设备的GPU绘制视图和动画。

答案 1 :(得分:1)

我建议你在两种情况下检查view.getBottom()的值(当它工作时和不工作时)。
它可能是因为view.getBottom()返回的值非常大而轻弹。
在代码中添加以下行:

Log.i("YourAppName", "view.getBottom(): -" + view.getBottom());
view.animate()
        .translationY(-view.getBottom())
        .alpha(0)
        .setDuration(HEADER_HIDE_ANIM_DURATION)
        .setInterpolator(new DecelerateInterpolator());

然后检查您的日志以查看值是否相同。

答案 2 :(得分:0)

我的方式略有不同。请注意,我正在使用的调用需要SDK 19(KitKat),但您仍然可以使用ViewPropertyAnimatorCompat

进行调用

我有一个FrameLayout,它有标题视图和主视图,前面有标题视图。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fab="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <include layout="@layout/main_layout" android:id="@+id/main_layout" />
    <include layout="@layout/header_layout" android:id="@+id/header_layout" />
</FrameLayout>

测量视图后(在onResume期间发布runnable)我将主视图的topPadding设置为标题的高度。

在隐藏和显示动画中,我添加了一个更新侦听器,在其中我将主视图的顶部填充更新为标题的高度+ Y上的翻译。

final View header = findViewById(R.id. header_layout);              
header.animate()
 .translationY(-header.getBottom())
 .setDuration(200)
 .setInterpolator(new DecelerateInterpolator())
 .setUpdateListener(new AnimatorUpdateListener() {          
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        int top = (int) (header.getHeight()+header.getTranslationY());
        findViewById(R.id.main_view).setPadding(0, top, 0, 0);
    }
 });

这使得它更平滑,因为填充与翻译一起更新。

实际上,使用ViewPropertyAnimatorCompat设置AnimationListener不起作用。从不调用监听器,因此为了向后兼容,我选择了这个解决方案,而不是优雅,但至少它适用于预KitKat设备:

final View mainView = findViewById(R.id.main_view);
Runnable mainUpdateRunnable = new Runnable() {          
    @Override
    public void run() {
        int top = (int) (header.getHeight()+header.getTranslationY());
        mainView.setPadding(0, top, 0, 0);
        if (mAnimatingHeader) {
            mainView.post(this);
        }
    }
};
mainView.post(mainUpdateRunnable);

使用AnimationListener(可以工作)

更新变量mAnimatingHeader