Jeff Bootsholz
Jeff Bootsholz

Reputation: 3068

Fragment pressing back button

I am now having an activity containing fragments

[1] , [2] , [3] , [4]

If pressing buttons , [3] , it can be redirected to [4]

I would like to implement the back button as shown follow..

when pressing back at [4] , it return to [3]

when pressing back at [3] , it return to [2]

when pressing back at [1] , the activity finishes();

When it comes to the current implementation, it finish the activity instead of popping up the Fragment. Would you please tell me what I should do or keep in mind ?

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

    if( keyCode==KeyEvent.KEYCODE_BACK) 
    {   

        finish();
    }       

        return super.onKeyDown(keyCode, event); 

}   

Upvotes: 44

Views: 139242

Answers (18)

Om Prakash Sharma
Om Prakash Sharma

Reputation: 1

Fragment Pressing Back Button - we are using popBackStack() function.

In Kotlin - write code in your activity

override fun onBackPressed() {
     super.onBackPressed()
     supportFragmentManager.popBackStack();
}

Upvotes: 0

Janibul Hoque Syeam
Janibul Hoque Syeam

Reputation: 1

just paste it in your activity main

 @Override
public void onBackPressed() {


    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
        getSupportFragmentManager().popBackStack();
    } else {
        finish();
    }


    
}

Upvotes: 0

Agilarasan anbu
Agilarasan anbu

Reputation: 2805

Try this, its helped me :)

 @Override  
    public void onResume() { //Pressed return button - returns to the results menu
        super.onResume();
        getView().setFocusableInTouchMode(true);
        getView().requestFocus();
        getView().setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
                    /*Here your code*/
                    return true;
                }
                return false;
            }
        });
    }

Upvotes: 0

Abhilash Das
Abhilash Das

Reputation: 1438

use this (in kotlin)

 activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            // in here you can do logic when backPress is clicked
        }
    })

i think this is the most elegant way to do it

Upvotes: 0

Hocine Kheddadji
Hocine Kheddadji

Reputation: 63

you can use this one in onCreateView, you can use transaction or replace

 OnBackPressedCallback callback = new OnBackPressedCallback(true) {
                @Override
                public void handleOnBackPressed() {
                    //what you want to do 
                }
            };
    requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);

Upvotes: 2

Haider Malik
Haider Malik

Reputation: 1771

In your onCreate() in your activity housing your fragments add a backstack change listener like so:

    fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            List<Fragment> f = fragmentManager.getFragments();
            Fragment frag = f.get(0);
            currentFragment = frag.getClass().getSimpleName();
        }
    });

(Nb. my fragmentManager is declared global) Now every time you change fragment the currentFragment String will become the name of the current fragment. Then in the activities onBackPressed() you can control the actions of your back button as so:

    @Override
    public void onBackPressed() {

    switch (currentFragment) {
        case "FragmentOne":
            // your code here 
            return;
        case "FragmentTwo":
            // your code here
            return;
        default:
            fragmentManager.popBackStack();
            // default action for any other fragment (return to previous)
    }

}

I can confirm that this method works for me.

Update : Kotlin

override fun onBackPressed() {

    when(supportFragmentManager.fragments[0].javaClass.simpleName){
        "FragmentOne" -> doActionOne()
        "FragmentTwo" -> doActionTwo()
        else -> supportFragmentManager.popBackStack()
    }
}

Upvotes: 5

Akshansh Jain
Akshansh Jain

Reputation: 87

if you are using webview inside a fragment than use this in your onCreateView method

webView.setOnKeyListener(new View.OnKeyListener(){

        @Override
        public boolean onKey(View view, int i, KeyEvent keyEvent) {
            if((i==KeyEvent.KEYCODE_BACK)&& webView.canGoBack()){
                webView.goBack();
                return true;
            }
            return false;
        }
    });

and import this class

import android.view.KeyEvent;

Upvotes: 4

hitesh
hitesh

Reputation: 378

Try this simple solution:

In your activity implement onBackPressed

 @Override
    public void onBackPressed() {
       if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
            getSupportFragmentManager().popBackStack();
        } else {
            finish();
        }
    }

This will work if you want to pop the top fragment on each back press. Note:- While adding fragment to activity always do add the transaction to back stack for this to work

Upvotes: 9

kamran hatami
kamran hatami

Reputation: 122

i use a methode to change fragments it has thw following code

 getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit).replace(R.id.content_frame, mContent, mContent.getClass().getSimpleName()).addToBackStack(null)
                .commit();

and for the back button this .

@Override
    public void onBackPressed() {
        // note: you can also use 'getSupportFragmentManager()'
        FragmentManager mgr = getSupportFragmentManager();
        if (mgr.getBackStackEntryCount() == 1) {
            // No backstack to pop, so calling super
            finish();
        } else {
            mgr.popBackStack();
        }
    }

the important thing to note is i use 1 for checking getBackStackEntryCount this is because if you dont use it and use 0 user sees nothing for the last back button.

Upvotes: 0

savepopulation
savepopulation

Reputation: 11921

This is a working solution for me:

dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
                    @Override
                    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                        if (keyCode == KeyEvent.KEYCODE_BACK) {
                            // DO WHAT YOU WANT ON BACK PRESSED
                            return true;
                        }
                        return false;
                    }
                });

Edit: You can replace dialog with getView() for fragments.

Upvotes: 9

Amit Kumar
Amit Kumar

Reputation: 817

Solution for Pressing or handling back button in Fragment.

The way I solved my issue I am sure it will helps you too:

1.If you don't have any Edit Text-box in your fragment you can use below code

Here MainHomeFragment is main Fragment (When I press back button from second fragment it will take me too MainHomeFragment)

    @Override
    public void onResume() {

    super.onResume();

    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {

            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){

                MainHomeFragment mainHomeFragment = new SupplierHomeFragment();
                android.support.v4.app.FragmentTransaction fragmentTransaction =
                        getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, mainHomeFragment);
                fragmentTransaction.commit();

                return true;    
            }    
            return false;
        }
    }); }

2.If you have another fragment named as Somefragment and it has Edit text-box then you can do it by this way.

private EditText editText;

Then In,

onCreateView():    
editText = (EditText) view.findViewById(R.id.editText);

Then Override OnResume,

@Override
public void onResume() {
    super.onResume();

    editText.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                editTextOFS.clearFocus();
                getView().requestFocus();
            }
            return false;
        }
    });

    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {

            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){

                MainHomeFragment mainHomeFragment = new SupplierHomeFragment();
                android.support.v4.app.FragmentTransaction fragmentTransaction =
                        getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.fragment_container, mainHomeFragment);
                fragmentTransaction.commit();

                return true;

            }

            return false;
        }
    });

}

That's all folks (amitamie.com) :-) ;-)

Upvotes: 5

Denny
Denny

Reputation: 149

You can use getFragmentManager().popBackStack() in basic Fragment to go back.

Upvotes: 3

Hiren Patel
Hiren Patel

Reputation: 52800

Easiest way ever:

onResume():

@Override
public void onResume() {
    super.onResume();

    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
                // handle back button's click listener
                Toast.makeText(getActivity(), "Back press", Toast.LENGTH_SHORT).show();
                return true;
            }
            return false;
        }
    });

}

Edit 1: If fragment having EditText.

private EditText editText;

onCreateView():

editText = (EditText) rootView.findViewById(R.id.editText);

onResume():

@Override
public void onResume() {
    super.onResume();

    editText.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                editText.clearFocus();
            }
            return false;
        }
    });

    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
                // handle back button's click listener
                Toast.makeText(getActivity(), "Back press", Toast.LENGTH_SHORT).show();
                return true;
            }
            return false;
        }
    });

}

Note: It will work if you have EditText in fragment.

Done

Upvotes: 62

mossman252
mossman252

Reputation: 512

Make sure to add the following:

if (event.getAction()!=KeyEvent.ACTION_DOWN)
                return true;

in the onKey block of code to avoid the event calling twice.

Upvotes: 1

What I do in this cases is I implement the onBackPressed() function from the Activity:

@Override
public void onBackPressed() {
   super.onBackPressed();
   FragmentManager fm = getSupportFragmentManager();
   MyFragment myFragment = (MyFragment) fm.findFragmentById(R.id.my_fragment);

   if((myFragmen.isVisible()){
      //Do what you want to do
   }
}

How this works for you too.

Upvotes: 4

Achin Kumar
Achin Kumar

Reputation: 767

Still better solution could be to follow a design pattern such that the back-button press event gets propagated from active fragment down to host Activity. So, it's like.. if one of the active fragments consume the back-press, the Activity wouldn't get to act upon it, and vice-versa.

One way to do it is to have all your Fragments extend a base fragment that has an abstract 'boolean onBackPressed()' method.

@Override
public boolean onBackPressed() {
   if(some_condition)
      // Do something
      return true; //Back press consumed.
   } else {
      // Back-press not consumed. Let Activity handle it
      return false;
   }
}

Keep track of active fragment inside your Activity and inside it's onBackPressed callback write something like this

@Override
public void onBackPressed() {
   if(!activeFragment.onBackPressed())
      super.onBackPressed();
   }
}

This post has this pattern described in detail

Upvotes: 4

Tejas Mehta
Tejas Mehta

Reputation: 1649

You also need to check Action_Down or Action_UP event. If you will not check then onKey() Method will call 2 times.

getView().setFocusableInTouchMode(true);
getView().requestFocus();

getView().setOnKeyListener(new OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (keyCode == KeyEvent.KEYCODE_BACK) {
                        Toast.makeText(getActivity(), "Back Pressed", Toast.LENGTH_SHORT).show();
                    return true;
                    }
                }
                return false;
            }
        });

Working very well for me.

Upvotes: 2

Kamel
Kamel

Reputation: 1077

This worked for me.

-Add .addToBackStack(null) when you call the new fragment from activity.

    FragmentTransaction mFragmentTransaction = getFragmentManager()
                .beginTransaction();
    ....
    mFragmentTransaction.addToBackStack(null);

-Add onBackPressed() to your activity

    @Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() == 0) {
        this.finish();
    } else {
        getFragmentManager().popBackStack();
    }
}

Upvotes: 92

Related Questions