0xh8h
0xh8h

Reputation: 3509

Exit app when press Back button in activity with multiple fragments in Navigation Drawer

I'm working on an app that need Navigation Drawer. This app has 1 MainActivity and about 10 fragments on it. When I click the Navigation Drawer icon in MainActivity it will show the 10 fragments so I can select each of them.

I choose fragment A, then B, then C...to F, for example. When I'm in fragment F and press the Back button, it will take me back to fragment E, then Back again it will take me to fragment D...

My problem is when I'm back to fragment A (from fragment B, of course) and press Back button one more time, it take me to a blank white screen (I think this is the main activity layout). And press Back one more time, the app will exit.

What I want is when I'm back to fragment A (last fragment) and hit Back, the app will exit immediately, not the blank white screen anymore

I've search on SO and found 1 similar question but no answer yet so I have to make another question

How can I do this? Thank you very much

Upvotes: 12

Views: 18496

Answers (11)

Hiren
Hiren

Reputation: 1591

This one worked for me (Exit double click to exit from Fragment)

  int backButtonCount = 0;


@SuppressLint({"ResourceAsColor", "ResourceType"})
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_home, container, false);
    //binding fragment view

    view.setFocusableInTouchMode(true);
    view.requestFocus();
    view.setOnKeyListener((v, keyCode, event) -> {
        Log.i("Fragment_Home", "keyCode: " + keyCode);
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {

            Log.e(TAG, "onCreateView: " + "Fragment Hom Key up");


            if (backButtonCount >= 1) {
                Intent intent = new Intent(Intent.ACTION_MAIN);
                intent.addCategory(Intent.CATEGORY_HOME);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                startActivity(intent);
                 getActivity().finish();


            } else {
                Toast.makeText(getContext(), "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
                backButtonCount++;


                new Handler().postDelayed(() -> {

                    backButtonCount = 0;

                }, 2000);

            }

Upvotes: 0

felix
felix

Reputation: 73

Use this.. Easy solution but works perfectly for me. This closes the application after you hit the last open fragment.

@Override
public void onBackPressed() {
    if(getSupportFragmentManager().getBackStackEntryCount() == 1) {
        moveTaskToBack(false);
    }
    else {
        super.onBackPressed();
    }
}

Upvotes: 1

Ranjithkumar
Ranjithkumar

Reputation: 18356

Very late answer. But I hope atleast help this answer anyone.

With help of following code I implement the double back press exit (It give Toast "Please click back again to exit" if press once more only app will exit.)

getBackStackEntryCount() - give the current count of your back stack fragments.

int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();

if this value==0 no fragments avilable in back stack. so execute the double back press exit code.

else allow the backpress action using super.onBackPressed();

@Override
public void onBackPressed() {

    int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
    //backStackEntryCount==0 -> no fragments more.. so close the activity with warning
    if (backStackEntryCount == 0){

        if (homePressed) {
            if (doubleBackToExitPressedOnce) {
                super.onBackPressed();

                return;
            }

            this.doubleBackToExitPressedOnce = true;
            Toast.makeText(this, "Please click back again to exit", Toast.LENGTH_SHORT).show();

            new Handler().postDelayed(new Runnable() {

                @Override
                public void run() {
                    doubleBackToExitPressedOnce = false;
                }
            }, 2000);
        } else {
            homePressed = true;
        }

}
    //some fragments are there.. so allow the back press action
    else {
        super.onBackPressed();
    }

}    

Globally declare these variables

boolean homePressed = true, doubleBackToExitPressedOnce = false;

Upvotes: 1

Xcross
Xcross

Reputation: 2132

This is what that worked for me.

If called from MainActivity

supportFinishAfterTransition();

If called from fragment

getActivity().supportFinishAfterTransition();

Upvotes: 0

Arpit Patel
Arpit Patel

Reputation: 8047

It's Easy way to exit your app just paste below code

 @Override
    public void onBackPressed() {
        FragmentManager manager = getSupportFragmentManager();

        if (manager.getBackStackEntryCount() > 1) {
            // If there are back-stack entries, leave the FragmentActivity
            // implementation take care of them.
            manager.popBackStack();

        } else {
            // Otherwise, ask user if he wants to leave :)
            new AlertDialog.Builder(this)
                    .setTitle("Really Exit?")
                    .setMessage("Are you sure you want to exit?")
                    .setNegativeButton(android.R.string.no, null)
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                        public void onClick(DialogInterface arg0, int arg1) {
                            // MainActivity.super.onBackPressed();
                            finish();
                            moveTaskToBack(true);
                        }
                    }).create().show();
        }

Upvotes: 1

Javad
Javad

Reputation: 6016

I just fixed my similar issue. I adapted Ali Azhar's solution. Since I have a splash screen activity, I didn't want to terminate the app, otherwise when I try to resume the app (pressing the active apps button on the phone and selecting the app), the app would get stuck in the splash screen without proceeding to my main activity. So instead of

MainActivity.super.onBackPressed();

I used this:

moveTaskToBack(true);

to show the home screen. I didn't need any exit confirmation by the user, so I removed the dialog code. I also wanted to adjust my replaceFragment(targetFragment, fragmentNameInBackStack) method to avoid adding the fragment to the backstack if it is the first fragment, but it turned out that there is no need to do that because we make the manager pop from the backstack if the are more than one fragment in the backstack, so if there is only one fragment, that's fine, we quit. It's good because I wanted to retain my back navigation behavior between different screens/fragments. So here is the code:

@Override
public void onBackPressed() {
    FragmentManager manager = getSupportFragmentManager();
    if (manager.getBackStackEntryCount() > 1 ) {
        manager.popBackStack();
    } else {
        // if there is only one entry in the backstack, show the home screen
        moveTaskToBack(true);
    }
}

Upvotes: 4

gambit
gambit

Reputation: 107

Remove addToBackStack() from your Fragment A. Hope that helps.

Upvotes: 8

Ali Azhar
Ali Azhar

Reputation: 1803

just exit the app at second last screen

  public void onBackPressed() {

    if (manager.getBackStackEntryCount() > 1 ) {
        // If there are back-stack entries, leave the FragmentActivity
        // implementation take care of them.
        manager.popBackStack();

    } else {
        // Otherwise, ask user if he wants to leave :)
        new AlertDialog.Builder(this)
                .setTitle("Really Exit?")
                .setMessage("Are you sure you want to exit?")
                .setNegativeButton(android.R.string.no, null)
                .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface arg0, int arg1) {
                        MainActivity.super.onBackPressed();
                    }
                }).create().show();
    }
}

Upvotes: 12

Friedolino
Friedolino

Reputation: 114

I guess I am the one with the other unanswered question, so I want to show you my workaround:

I check if there is one child in my FrameLayout. If there is one, I will go one fragment back. And check again. Because I do only know the whitescreen for sure, I need to check after it for 0 childs left. If there exist still another fragment, there is nothing to do anymore, but if childs == 0, you want to ask for leaving the activity.

Alternatively you can remove the AlertDialog and close the app if you reach this last fragment.

@Override
public void onBackPressed() {
    FrameLayout fl = (FrameLayout) findViewById(R.id.content_frame);
    if (fl.getChildCount() == 1) {
        super.onBackPressed();
        if (fl.getChildCount() == 0) {
            new AlertDialog.Builder(this)
                    .setTitle("Close App?")
                    .setMessage("Do you really want to close this beautiful app?")
                    .setPositiveButton("YES",
                            new DialogInterface.OnClickListener() {

                                @Override
                                public void onClick(DialogInterface dialog,
                                        int which) {
                                    finish();
                                }
                            })
                    .setNegativeButton("NO",
                            new DialogInterface.OnClickListener() {

                                @Override
                                public void onClick(DialogInterface dialog,
                                        int which) {
                                }
                            }).show();
            // load your first Fragment here
        }
    } else if (fl.getChildCount() == 0) {
        // load your first Fragment here
    } else {
        super.onBackPressed();
    }
}

Upvotes: 6

Naren
Naren

Reputation: 1

I guess you can either avoid the back button press or finish the activity on back button pressed.Generally if you are using Navigation Drawer than this would not be the problem at all but you can try.

    @Override
public void onBackPressed()
{
    // Do Here what ever you want do on back press;
}

or you can go for Navigation Drawer http://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/

Upvotes: 0

Sush
Sush

Reputation: 3874

In onBack method check no of fragments available in the with fragment manager... If its of its 1 then close the application using move taskback method

Upvotes: 0

Related Questions