Глюк при удалении TabLayout из AppBarLayout с помощью removeView () - PullRequest
0 голосов
/ 26 апреля 2018

При нажатии на элемент в представлении переработчика я называю это

appbar.removeView(tabs)

Это видео показывает, что происходит

Кажется, что убрать TabLayout полностью без анимации, затем добавить его обратно, а затем использовать анимацию, чтобы удалить его. Я замедлил переход, чтобы показать, что он делает.

это также происходит при добавлении их обратно вот так

if (tabs.parent != null) {
        (tabs.parent as ViewGroup).removeView(tabs)
    }
    appbar.addView(tabs)
    appbar.setExpanded(true, true)

Вот мой макет

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator_main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:theme="@style/Theme.AppCompat.Light.NoActionBar">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:animateLayoutChanges="true"
        app:elevation="0dp"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar">

        <android.support.v7.widget.Toolbar
            xmlns:android="http://schemas.android.com/apk/res/android"
            style="@style/MyToolbar"
            android:id="@+id/toolbar"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            app:layout_scrollFlags="scroll|enterAlways|snap"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabTextAppearance="@style/TabText"
            android:layout_marginRight="@dimen/small_spacing"
            android:layout_marginLeft="@dimen/small_spacing"
            app:tabMode="fixed"
            app:tabGravity="fill"
            app:tabIndicatorHeight="2dp"
            app:layout_scrollFlags="enterAlways"/>

    </android.support.design.widget.AppBarLayout>


    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/appbar"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" >

        <***.***.CustomViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </FrameLayout>

</android.support.design.widget.CoordinatorLayout>

Ответы [ 3 ]

0 голосов
/ 31 августа 2018

Вы можете скрыть макет вкладки с анимацией, как это.

tabLayout.animate().scaleY(0).setInterpolator(new AccelerateInterpolator()).start();

еще не проверял на моей стороне. Пожалуйста, прокомментируйте, если у вас есть какие-либо проблемы по этому вопросу. Возможно, это должно сработать.

0 голосов
/ 01 сентября 2018

Так что же происходит?

Кажется, все работает нормально, кроме той вспышки, о которой вы упоминаете. Я взял приложение Cheese Square Криса Бейнса и сделал несколько модификаций, чтобы дублировать то, что вы видите. Нажатие FAB удаляет и добавляет вкладки.

Вот видео того, что я придумал.

enter image description here

Вот снимок экрана проблемы, когда TabLayout удален. Как видите, RecyclerView перекрывает панель приложения.

enter image description here

Вот снимок экрана проблемы, когда TabLayout добавляется обратно. Здесь вы можете видеть, что RecyclerView сдвигается вниз в свою позицию после добавления вида.

enter image description here

Переход макета исчезающего TabLayout выполняется с помощью LayoutTransition. Чтобы сделать эффективный переход, LayoutTransition должен определить, как выглядит окончательный макет, чтобы можно было создать набор анимаций. Это требует выкладки того, как будет выглядеть экран после перехода. появляется , что окончательный макет отображается незадолго до запуска анимации. (Мое предположение.) Это может быть состояние гонки или это может быть связано с этой оговоркой :

Этот класс и связанный с ним флаг XML для контейнеров animateLayoutChanges = "true" предоставляют простую утилиту, предназначенную для автоматизации изменений в простых ситуациях. Использование LayoutTransition на нескольких уровнях иерархии вложенного представления может не работать из-за взаимосвязи различных уровней макета. Кроме того, контейнер, который прокручивается одновременно с добавлением или удалением элементов, вероятно, не является подходящим кандидатом для этой утилиты, поскольку местоположения до / после, рассчитанные с помощью LayoutTransition, могут не совпадать с фактическими местоположениями, когда анимация заканчивается из-за контейнер прокручивается при запуске анимации. Вы можете обойти эту конкретную проблему, отключив «изменяющиеся» анимации, установив для анимаций CHANGE_APPEARING и CHANGE_DISAPPEARING значение null и соответственно установив startDelay других анимаций.

Престижность и репутация тому, кто может точно выяснить, что происходит. (Эта проблема может быть артефактами, упомянутыми в следующем загадочном комментарии в коде для LayoutTransition:)

/**
 * Controls whether changing animations automatically animate the parent hierarchy as well.
 * This behavior prevents artifacts when wrap_content layouts snap to the end state as the
 * transition begins, causing visual glitches and clipping.
 * Default value is true.
 */
private boolean mAnimateParentHierarchy = true;

Как это исправить?

Я предлагаю вам вообще отказаться от LayoutTransitions (android:animateLayoutChanges="false") и перейти к TransitionManager.

Мы воспользуемся удобным методом TransitionManager#beginDelayedTransition:

beginDelayedTransition

void beginDelayedTransition (ViewGroup sceneRoot, Переходный переход)

Удобный метод для анимации новой сцены, определяемый всеми изменениями в данном корне сцены между вызовом этого метода и следующим кадром рендеринга. Вызов этого метода приводит к тому, что TransitionManager захватывает текущие значения в корне сцены, а затем отправляет запрос на выполнение перехода в следующем кадре. В это время новые значения в корне сцены будут записаны, а изменения будут анимированы. Нет необходимости создавать сцену; это подразумевается изменениями, которые происходят между вызовом этого метода и следующим кадром, когда начинается переход.

Вот мой код для удаления и добавления вкладок. Обязательно установите animateLayoutChanges="false".

fab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (mTabsAdded) {
            // Get rid of the indicator due to an on-screen artifact.
            tabs.setSelectedTabIndicatorHeight(0);
            TransitionSet set = new TransitionSet()
                .addTransition(new Fade(OUT))
                .addTransition(new ChangeBounds());
            TransitionManager.beginDelayedTransition(layout, set);
            mAppBar.removeView(tabs);
        } else {
            // Add tab indicator back in.
            int indicatorHeight = (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, 2,
                getResources().getDisplayMetrics());
            tabs.setSelectedTabIndicatorHeight(indicatorHeight);
            TransitionSet set = new TransitionSet()
                .addTransition(new Fade(IN))
                .addTransition(new ChangeBounds());
            TransitionManager.beginDelayedTransition(layout, set);
            mAppBar.addView(tabs);
        }
        mTabsAdded = !mTabsAdded;
    }
});

enter image description here

0 голосов
/ 25 августа 2018

Из видео похоже, что есть три фрагмента, которые загружаются в соответствии с TabLayout. MyPhotosFragment, MyAlbumsFragment и MyFavouritesFragment.

Если я правильно понимаю, вы помещаете TabLayout в упражнении, и эти три фрагмента загружаются непосредственно в упражнение. Когда в ящике выбрано «Скрытые альбомы», панель приложения отображается / добавляется, и она скрывается / удаляется при выборе другого элемента.

Что вам нужно сделать, это создать новый фрагмент, который будет действовать как контейнер. Давайте назовем это HiddenAlbumsFragment. Затем вы должны удалить TabLayout и ViewPager из упражнения и поместить их в HiddenAlbumsFragment. При нажатии на элемент вкладки HiddenAlbumsFragment должен загрузить соответствующий фрагмент как субфрагмент. Затем, когда вы замените HiddenAlbumsFragment на другой, выбрав один из них, вкладка автоматически исчезнет.

...