wake-up-neo.com

Android Navigation Component Pop zu Übergangsproblem

Ich habe 2 Aktionen

Aktion1

 <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" />

Aktion2

<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" />

Was ich will, ist, wenn die zweite Aktion ausgelöst wird, möchte ich den hinteren Stapel löschen und nur loginFragment so einstellen, dass es im Stapel bleibt.

nur ein problem ist, wenn ich die action2 durchführe, wird 'slide_out_right' als exit-animation ausgeführt

Ich verstehe, dass, wenn wir das Fragment aus dem Stapel ziehen, das 'popExitAnim' von action1 anstelle von 'exitAnim' von action2 ausgelöst wird.

aber ich möchte wissen, wie ich das Fragment dazu bringen kann, slide_out_left Animation für das Verlassen durchzuführen und es auch aus dem Stapel heraus zu knallen.

10
jaydeep_gedia

Am Ende habe ich onCreateAnimation in dem Fragment überschrieben, das navigate aufruft. In diesem Beispiel wird gezeigt, wie Sie durch verschachtelte Navigationsdiagramme nach ID navigieren und die Bedingung pop Animation beenden (oder popExitAnim) ersetzen.

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)
}

Beachten Sie, dass diese besondere Situation teilweise auf die Richtcharakteristik von Folienanimationen zurückzuführen ist.

6
maxbeaudoin

Dies ist etwas schwierig zu lösen, da NavOptions intern von den praktischen Methoden behandelt wird, die zum Binden Ihrer Schublade an das Navigationsdiagramm verwendet werden. Ich habe diese Lösung ursprünglich mit dem Einstellungsmenü und onOptionsItemSelected getestet, aber die Grundidee sollte auch hier funktionieren.

Stellen Sie zunächst sicher, dass Ihre Menüelement-IDs denen Ihrer Navigationsfragmente entsprechen:

<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>

Anstatt nun die vorgefertigten Methoden zum Verbinden der Schublade mit Ihrem NavController zu verwenden , implementieren Sie NavigationView.OnNavigationItemSelectedListener In Ihrer NavHost-Aktivität und überschreiben Sie die Methode onNavigationItemSelected wie folgt:

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

Dadurch wird die Auswahl als Navigation in Ihrer Grafik weitergeleitet. Ersetzen Sie your_nav_Host_fragment Durch die Fragment-ID, für die Sie app:defaultNavHost="true" Festgelegt haben.

Sie werden feststellen, dass dies zwar funktioniert, die Folienanimationen jedoch standardmäßig verwendet werden. Dies liegt daran, dass der Aufruf NavigationUI intern einen eigenen NavOptions mit den folgenden Einstellungen erstellt:

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);

Leider verwendet die Methode noch kein NavOptions.Builder Als Argument, aber Sie können eine Utility-Klasse auf der Basis des Android Quellcodes) erstellen, um die Funktionalität nachzuahmen:

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;
    }
}

Schließlich können Sie in Ihrer Aktivität jetzt den Aufruf von NavigationUI durch den in NavigationUIHelper implementierten ersetzen:

@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);
}

Auf diese Weise können Sie die Zeichnungsübergangsanimationen nach Ihren Wünschen ändern, ohne die Navigationskomponente ersetzen zu müssen.

2
Jonatan