Search code examples
androidandroid-fragmentsnavigationfragmentandroid-architecture-navigation

Android popper navigation with Navigation component


I have two fragments FirstFragment and WelcomeFragment ,

in FirstFragment i have some animation and i load data from server then i navigate to WelcomeFragment using NavController :

navController.navigate(R.id.action_firstFragment_to_welcomeFragment);

and my nav_graph is like this :

<fragment
        android:id="@+id/firstFragment"
        android:name="com.flyeducation.UI.FirstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first">
        <action
            android:id="@+id/action_firstFragment_to_welcomeFragment"
            app:destination="@id/welcomeFragment"
            app:enterAnim="@anim/fade_in"
            app:exitAnim="@anim/fade_out"
            app:popEnterAnim="@anim/fade_in"
            app:popExitAnim="@anim/fade_out" />
    </fragment>

i want ot have this behaviour :

navigating from FirstFragment to WelcomeFragment but not having the ability to go back to FirstFragment when pressing the back button the app should close like pressing the home Button and when coming back staying in the WelcomeFragment

from the documentation i tried in the nav_graph XML :

app:popUpTo="@id/firstFragment"
app:popUpToInclusive="true"

the app closes but when i go back to it , it does start all over again from the FirstFragment and not maintaining the state that i want which is staying in WelcomeFragment

from other questions i also tried this in WelcomeFragment :

navController.popBackStack(R.id.firstFragment, true);

Anyone can help me achieving the wanted behaviour

EDIT :

I ended up intercepting the onKeyDown and also Simulating Home click when it onKeyDown is pressed on my WelcomeFragment

This in my WelcomeFragment

public void myOnKeyDown(int key_code, Context context){
        openDialog(context);
    }

    public void openDialog(final Context context) {
            new AlertDialog.Builder(context)
                    .setTitle("Exit ! ")
                    .setMessage("Are you sure you wanna quit our App , we will miss you !")
                    .setNegativeButton(android.R.string.cancel, null) // dismisses by default
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent i = new Intent(Intent.ACTION_MAIN);
                            i.addCategory(Intent.CATEGORY_HOME);
                            context.startActivity(i);
                        }
                    })
                    .create()
                    .show();
        }

and this in my Activity :

@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        ((WelcomeFragment) WelcomeFragment).myOnKeyDown(keyCode, this);
        return false ;
    }

This has give me the behaviour i want but i do not think it is best practice


Solution

  • So this is the right solution to be used in my case , it will have the same behaviour described in the question and like what i had when overriding onKeyDown in MainActivity

    OnBackPressedCallback callback = new OnBackPressedCallback(true /* enabled by default */) {
                @Override
                public void handleOnBackPressed() {
                    openDialog(getContext());
                }
            };
            requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), callback);
    

    Another clue :

    app:popUpTo="@id/fragment" 
    

    is used when the fragment is in the back stack

    and

    app:popUpToInclusive="true"
    

    will clear the stack untill hitting the fragment id in app:popUpTo

    described here popUpTo and popUpToInclusive