Анимируйте переходы фрагментов с помощью панели навигации или меню панели инструментов - PullRequest
2 голосов
/ 07 августа 2020

У меня есть панель навигации и меню панели инструментов, где я могу go перейти к другому фрагменту. Я использовал это для навигации:

override fun onNavigationItemSelected(item: MenuItem): Boolean
{
    drawerLayout.close()
    return NavigationUI.onNavDestinationSelected(
        item,
        findNavController(R.id.navHostFragment)
    )
}

Как я могу добавить пользовательскую анимацию при переключении фрагментов?


Это Answer your own question. Я столкнулся с этой проблемой и не смог найти ни одного ответа, который бы работал на 100% в моем случае, так что, возможно, это кому-то поможет.

1 Ответ

1 голос
/ 07 августа 2020

Так должен выглядеть замещенный метод onNavigationItemSelected:

override fun onNavigationItemSelected(item: MenuItem): Boolean
{
    drawerLayout.close()

    // this part checks if current fragment is the same as destination
    return if (findNavController(R.id.navHostFragment).currentDestination?.id != item.itemId)
    {
        val builder = NavOptions.Builder()
            .setLaunchSingleTop(true)
            .setEnterAnim(R.anim.enter_left_to_right)
            .setExitAnim(R.anim.exit_right_to_left)
            .setPopEnterAnim(R.anim.popenter_right_to_left)
            .setPopExitAnim(R.anim.popexit_left_to_right)

        // this part set proper pop up destination to prevent "looping" fragments
        if (item.order and Menu.CATEGORY_SECONDARY == 0)
        {
            var startDestination: NavDestination? =
                findNavController(R.id.navHostFragment).graph

            while (startDestination is NavGraph)
            {
                val parent = startDestination
                startDestination = parent.findNode(parent.startDestination)
            }

            builder.setPopUpTo(
                startDestination!!.id,
                false
            )
        }

        val options = builder.build()
        return try
        {
            findNavController(R.id.navHostFragment).navigate(item.itemId, null, options)
            true
        }
        catch (e: IllegalArgumentException) // couldn't find destination, do nothing
        {
            false
        }
    }
    else
    {
        false
    }
}
  1. Этот метод предотвращает переход к текущим выбранным фрагментам. Поэтому, когда пользователь находится в Fragment A и в панели навигации снова выбирает Fragment A, ничего не произойдет, панель навигации просто скроется.

  2. Этот метод также предотвращает "зацикливание" фрагментов , в стеке может быть только один фрагмент, который был выбран в панели навигации или меню панели инструментов. Например, в панели навигации есть Fragment A и Fragment B. Пользователь находится в Fragment Home, затем от go до Fragment A и рядом с Fragment B. Если пользователь нажимает кнопку "Назад", приложение go вернется к Fragment Home, а не к Fragment A. Кроме того, вместо поиска startDestination через некоторое время l oop можно использовать R.id.homeFragment. Если кто-то хочет разрешить "зацикливание" фрагментов, просто удалите эту часть кода.

Я протестировал это решение, и, похоже, оно работает хорошо, но, конечно, может быть что-то, что работает не так, как должно.


Если кому-то нужна простая анимация с постепенным проявлением / исчезновением и вертикальным перемещением:

R.anim.enter_left_to_right

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@integer/fragment_anim_time"
        android:fromXDelta="-100%"
        android:fromYDelta="0%"
        android:toXDelta="0%"
        android:toYDelta="0%" />
    <alpha
        android:duration="@integer/fragment_anim_time"
        android:fromAlpha="0.5"
        android:toAlpha="1" />
</set>

R.anim.exit_right_to_left

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@integer/fragment_anim_time"
        android:fromXDelta="0%"
        android:fromYDelta="0%"
        android:toXDelta="100%"
        android:toYDelta="0%" />
    <alpha
        android:duration="@integer/fragment_anim_time"
        android:fromAlpha="1"
        android:toAlpha="0.5" />
</set>

R.anim.popenter_right_to_left

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@integer/fragment_anim_time"
        android:fromXDelta="100%"
        android:fromYDelta="0%"
        android:toXDelta="0%"
        android:toYDelta="0%" />
    <alpha
        android:duration="@integer/fragment_anim_time"
        android:fromAlpha="0.5"
        android:toAlpha="1" />
</set>

R.anim.popexit_left_to_right

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@integer/fragment_anim_time"
        android:fromXDelta="0%"
        android:fromYDelta="0%"
        android:toXDelta="-100%"
        android:toYDelta="0%" />
    <alpha
        android:duration="@integer/fragment_anim_time"
        android:fromAlpha="1"
        android:toAlpha="0.5" />
</set>

res / значения / целые числа. xml

<integer name="fragment_anim_time">250</integer>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...