我正试图为视图设置动画,并在一些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(有效)进行更新