我想要一个动画效果,就像在 YouTube 或 Gmail 应用程序中一样。向下滚动时,顶部栏在屏幕上线的外侧平移,反之亦然。但我的情况略有不同,我的屏幕布局如下:
关于上面的屏幕布局:
视图 0有一些文本显示区域。
视图 1在视图 3 内的列表视图的向上滚动时预计在视图 0 后面翻译
视图 2也将在视图 3 中同一列表视图向上滚动事件的视图 0 的上方和下方进行转换,但此时它将在视图 0 下方的屏幕上保持可见,此时视图 1 将完全隐藏在视图 0 后面。
视图 3是包含区域的列表视图,即使在视图 2 向上翻译之后,它也应该低于视图 2。
幸运的是,我看到了这篇文章,它完成了我想要实现的完全相同的事情,根据我的要求进行了少量大小调整它同时拥有 View 1 和 2,但只有 View 1 的高度,导致 View 2 在 View 0 下方保持可见。
现在我在这里面临的问题是在翻译时,在视图 1 和视图 2 的原始位置创建了新的空白区域。如下面的屏幕所示:
实际上,所有 View 0 到 3 都是相对布局,它们是在也是相对布局的父级中定义的。View 3 在 View 2 下方具有属性。但是在平移动画后 View 3 停留在它开始时的位置,只有 View 2 向上移动。
我尝试将 View 3 作为平移动画的一部分,在这种情况下,它会随着 View 2 向上移动,但在其底部(View 3)会留下空白区域。为什么会发生这种情况?即使在动画之后,我应该怎么做才能将 View 3 保持在 View 2 以下?
ViewPropertyAnimator 的 Android 博客: https ://android-developers.googleblog.com/2011/05/introducing-viewpropertyanimator.html
我为这个解决方案搜索了很多我尝试了不同的东西但没有任何效果最后我想我应该发布问题,以便如果任何已经遇到过此类问题的人可能会有帮助。
感谢您阅读这个巨大的问题。
这是代码:
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/top_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--
Some text views for information
-->
<RelativeLayout
android:id="@+id/container_veiw"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Below view holds view 2 at the bottom -->
<RelativeLayout
android:id="@+id/animate_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:fillAfter="true"
android:fillEnabled="true">
<!-- Below relative layout is xepected to be hidden behind top area -->
<!-- Below is view 1 in diagram -->
<RelativeLayout
android:id="@+id/animate_child"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="@color/black_background">
<LinearLayout
android:id="@+id/some_other_views"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_alignParentTop="true"
android:layout_margin="16dp"
android:animateLayoutChanges="true"
android:orientation="horizontal">
<!-- Some child views -->
</LinearLayout>
</RelativeLayout>
<!-- This is view 2 -->
<RelativeLayout
android:id="@+id/view2"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_below="@id/animate_child"
android:background="@android:color/white">
<!-- Some child views -->
</RelativeLayout>
</RelativeLayout>
<!-- At this place after animation empty area is getting created -->
<!-- Below relative layout is expected to be just below @id/animate_parent -->
<!-- This is view 3 -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="@id/animate_parent"
android:background="#ffffff">
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:fadeScrollbars="false"
android:scrollbarAlwaysDrawVerticalTrack="true"
tools:listitem="@layout/fragment_document" />
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
Java 代码:
在回收站视图上滚动监听器:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (scrollingUp) {
if (verticalOffset > animate_child.getHeight()) {
animateHide();
} else {
animateShow(verticalOffset);
}
} else {
if (animate_child.getTranslationY() < animate_child.getHeight() * -0.6 && verticalOffset > animate_child.getHeight()) {
animateHide();
} else {
animateShow(verticalOffset);
}
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
verticalOffset += dy;
scrollingUp = dy > 0;
int toolbarYOffset = (int) (dy - animate_parent.getTranslationY());
animate_parent.animate().cancel();
if (scrollingUp) {
if (toolbarYOffset < animate_child.getHeight()) {
if (verticalOffset > animate_child.getHeight()) {
toolbarSetElevation(ELEVATION_CONSTANT);
}
animate_parent.setTranslationY(-toolbarYOffset);
} else {
toolbarSetElevation(0);
animate_parent.setTranslationY(-animate_child.getHeight());
}
} else {
if (toolbarYOffset < 0) {
if (verticalOffset <= 0) {
toolbarSetElevation(0);
}
animate_parent.setTranslationY(0);
} else {
if (verticalOffset > animate_child.getHeight()) {
toolbarSetElevation(ELEVATION_CONSTANT);
}
animate_parent.setTranslationY(-toolbarYOffset);
}
}
}
});
辅助功能:
private void animateShow(final int verticalOffset) {
animate_parent.animate()
.translationY(0)
.setInterpolator(new LinearInterpolator())
.setDuration(180)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
setElevation(verticalOffset == 0 ? 0 : ELEVATION_CONSTANT);
}
});
}
private void animateHide() {
animate_parent.animate()
.translationY(-animate_child.getHeight())
.setInterpolator(new LinearInterpolator())
.setDuration(180)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setElevation(0);
}
});
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void setElevation(float elevation) {
// setElevation() only works on Lollipop
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
animate_parent.setElevation(elevation);
}
}