平滑“视图”的隐藏/显示动画和填充空白空间的第二个视图



我正试图为视图设置动画,并在一些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

动画效果。。。但我认为,由于我的customview不是一个具有覆盖属性的操作栏,customviews不会离开,下面的LinearLayout不会填补空白(没有)。

因此,我使用了一个animationlistener,并在动画结束时将customview可见性设置为消失,但当你接近触发动画的预期Y点时,它会以可怕的方式轻弹(随着customwiew可见性消失而轻弹,下面的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点周围缓慢滚动时它将如何轻弹的注释。

我建议您在Manifest文件中使用android:hardwareAccelerated="true"属性。它将使用您设备的GPU来绘制视图和动画。

我建议您在这两种情况下都检查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());

然后检查日志,看看这些值是否相同。

我用了一种稍微不同的方式。注意,我使用的调用需要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期间发布可运行的视图),我将主视图的topPadding设置为页眉的Height。

在隐藏和显示动画中,我添加了一个更新侦听器,并在其中更新主视图的顶部填充为标题的高度+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);

变量mAnimatingHeader使用AnimationListener(有效)进行更新

最新更新