Android Navigation Component всплывающее окно для перехода - PullRequest
0 голосов
/ 30 декабря 2018

У меня есть 2 действия

Action1

 <action
        android:id="@+id/actionBaseFragmentToAskForLocation"
        app:destination="@+id/introAskForLocationFragment"
        app:enterAnim="@anim/slide_in_right"
        app:exitAnim="@anim/slide_out_left"
        app:popEnterAnim="@anim/slide_in_left"
        app:popExitAnim="@anim/slide_out_right" />

Action2

<action
        android:id="@+id/actionIntroAskLocationToLogin"
        app:destination="@id/loginFragment"
        app:enterAnim="@anim/slide_in_right"
        app:exitAnim="@anim/slide_out_left"
        app:popEnterAnim="@anim/slide_in_right"
        app:popExitAnim="@anim/fade_out"
        app:popUpTo="@+id/app_main_navigation" />

То, что я хочу, это когда запускается второе действие, я хочу очистить задний стеки установить только loginFragment, чтобы он оставался в стеке.

только одна проблема - когда я выполняю Action2, 'slide_out_right' выполняется как анимация выхода

Я понимаю, что если мы вытолкнем фрагмент изстек 'popExitAnim' из action1 будет запущен вместо 'exitAnim' из action2.

, но я хочу знать, как заставить фрагмент выполнить анимацию slide_out_left для выхода, а также вытащить его из стека.

Ответы [ 2 ]

0 голосов
/ 24 апреля 2019

В итоге я переопределил onCreateAnimation во фрагменте, который вызывает navigate.В этом примере показано, как перемещаться по вложенным навигационным графам по идентификатору и заменять условно pop анимацию выхода (или popExitAnim) условно.

override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
    val navController = findNavController()
    val graph = navController.graph.findNode(R.id.onboardingGraph) as NavGraph
    val dest = graph.findNode(R.id.confirmationFragment)
    if (!enter && dest != null && navController.currentDestination?.id == dest.id) {
        return AnimationUtils.loadAnimation(requireContext(), R.anim.slide_out_left)
    }
    return super.onCreateAnimation(transit, enter, nextAnim)
}

Обратите внимание, что эта конкретная ситуация частично обусловленанаправленная природа анимации слайдов.

0 голосов
/ 19 марта 2019

Это довольно сложно решить, поскольку NavOptions внутренне обрабатывается удобными методами, используемыми для привязки вашего ящика к навигационной диаграмме.Первоначально я протестировал это решение с меню настроек и onOptionsItemSelected, но основная идея должна работать и здесь.

Сначала убедитесь, что идентификаторы пунктов вашего меню соответствуют идентификаторам ваших фрагментов навигации:

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    ...

    <item android:id="@+id/example_id" ... />
</menu>
<navigation xmlns:android="http://schemas.android.com/apk/res/android" ... >

    ...

    <fragment android:id="@+id/example_id" ... />
</navigation>

Теперь вместо использования готовых методов для подключенияв свой NavController Реализуйте NavigationView.OnNavigationItemSelectedListener в своей деятельности NavHost и переопределите метод onNavigationItemSelected следующим образом:

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    NavHost navHost = Navigation.findNavController(this, R.id.your_nav_host_fragment);
    return NavigationUI.onNavDestinationSelected(item, navHost);
}

Это перенаправит выделение в виде навигации на вашем графике.Замените your_nav_host_fragment идентификатором фрагмента, для которого вы установили app:defaultNavHost="true".

. Вы заметите, что, пока это работает, по умолчанию все равно используются анимации слайдов.Это связано с тем, что вызов NavigationUI внутренне создает свой собственный NavOptions со следующими настройками:

NavOptions.Builder builder = new NavOptions.Builder()
                .setLaunchSingleTop(true)
                .setEnterAnim(R.anim.nav_default_enter_anim)
                .setExitAnim(R.anim.nav_default_exit_anim)
                .setPopEnterAnim(R.anim.nav_default_pop_enter_anim)
                .setPopExitAnim(R.anim.nav_default_pop_exit_anim);

К сожалению, метод еще не принимает NavOptions.Builder в качестве аргумента, ноВы можете создать служебный класс на основе исходного кода Android, чтобы имитировать функциональность:

public class NavigationUIHelper {
    public static boolean onNavDestinationSelected(@NonNull MenuItem item,
                                                   @NonNull NavController navController,
                                                   @NonNull NavOptions.Builder builder) {
        if ((item.getOrder() & Menu.CATEGORY_SECONDARY) == 0) {
            NavDestination destination = findStartDestination(navController.getGraph());
            builder.setPopUpTo(destination.getId(), false);
        }
        NavOptions options = builder.build();
        try {
            navController.navigate(item.getItemId(), null, options);
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }

    // Need to copy this private method as well
    private static NavDestination findStartDestination(@NonNull NavGraph graph) {
        NavDestination startDestination = graph;
        while (startDestination instanceof NavGraph) {
            NavGraph parent = (NavGraph) startDestination;
            startDestination = parent.findNode(parent.getStartDestination());
        }
        return startDestination;
    }
}

Наконец, в своей деятельности вы теперь можете заменить вызов NavigationUI на вызов, реализованный в NavigationUIHelper:

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    NavHost navHost = Navigation.findNavController(this, R.id.your_nav_host_fragment);
    NavOptions.Builder builder = new NavOptions.Builder()
                .setLaunchSingleTop(true)
                .setEnterAnim(R.anim.custom_enter)
                .setExitAnim(R.anim.custom_exit)
                .setPopEnterAnim(R.anim.custom_pop_enter)
                .setPopExitAnim(R.anim.custom_pop_exit);
    return NavigationUIHelper.onNavDestinationSelected(item, navHost, builder);
}

Это должно позволить вам изменять анимацию перехода ящика в соответствии с вашими предпочтениями, не заменяя компонент навигации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...