После того, как ViewPropertyAnimator переведет анимацию в View, пустое пространство будет создано в относительном макете?
Я хотел анимированный эффект, как в приложении YouTube или Gmail. Где верхняя полоса переходит наружу от верхней линии экрана при прокрутке вниз и наоборот. Но мой случай немного отличается, мой экран выглядит следующим образом:
О макете экрана выше:
Представление 0 имеет некоторую текстовую область отображения.
Вид 1, который, как ожидается, будет переведен за Вид 0 при увеличении прокрутки списка, который находится внутри Вид 3
Представление 2 будет также транслироваться выше и чуть ниже Представления 0 в том же событии повышения прокрутки представления списка в Представлении 3, но оно останется видимым на экране чуть ниже Представления 0 в этой точке. Представление 1 будет полностью скрыто за Представлением 0.
Представление 3 является списком, содержащим область, и ожидается, что оно будет находиться под представлением 2 даже после перевода представления 2.
К счастью, я читаю эту статью, которая делает то же самое, чего я хочу достичь, с небольшими изменениями размера в соответствии с моими требованиями. Я могу перевести представление 1 за представление 0 и представление 2 чуть ниже представления 0. Перевод предоставляется родителю. который содержит оба вида 1 и 2, но имеет только высоту вида 1, причина этого вида 2 остается видимой ниже вида 0.
Теперь проблема, с которой я сталкиваюсь, заключается в том, что при переводе создается новая пустая область в исходных позициях вида 1 и вида 2. Как показано на экране ниже:
На самом деле все представления от 0 до 3 являются относительными макетами, и они определены в родительском элементе, который также является относительным макетом. У View 3 есть свойство ниже View 2. Но после анимации перевода View 3 остается в том положении, в котором он был в начале, только View 2 перемещается вверх.
Я попытался поместить View 3 как часть анимации перевода, в этом случае он перемещается вместе с View 2 вверх, но в нижней части ( View 3) остается пустое пространство. Почему это может случиться? Что я должен сделать, чтобы сохранить вид 3 ниже вида 2 даже после анимации?
Вот статья, за которой я следовал: https://rylexr.tinbytes.com/2015/04/27/how-to-hideshow-android-toolbar-when-scrolling-google-play-musics-behavior/
Блог Android для ViewPropertyAnimator: 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);
}
}