После того, как ViewPropertyAnimator переведет анимацию в View, пустое пространство будет создано в относительном макете?

Я хотел анимированный эффект, как в приложении YouTube или Gmail. Где верхняя полоса переходит наружу от верхней линии экрана при прокрутке вниз и наоборот. Но мой случай немного отличается, мой экран выглядит следующим образом:

О макете экрана выше:

  1. Представление 0 имеет некоторую текстовую область отображения.

  2. Вид 1, который, как ожидается, будет переведен за Вид 0 при увеличении прокрутки списка, который находится внутри Вид 3

  3. Представление 2 будет также транслироваться выше и чуть ниже Представления 0 в том же событии повышения прокрутки представления списка в Представлении 3, но оно останется видимым на экране чуть ниже Представления 0 в этой точке. Представление 1 будет полностью скрыто за Представлением 0.

  4. Представление 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);
        }
}

0 ответов

Другие вопросы по тегам