I want to manage backpress in fragment , i know to handle brackpress in activity by calling onBackpress method.
#Override
public void onBackPressed() {
super.onBackPressed();
}
But i implemented fragment in to the activity and its replace morethan 10+ times , so whenever i press back key apps close.
so i want to manage backpress in fragment with multiple time.
if anyone know best solution then please give your answer , i already tried many solution given by similar question but its not working.
Thanks in Advance :)
You can used This way handle backpress on Fragment
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (getView() != null) {
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN)
if (keyCode == KeyEvent.KEYCODE_BACK)
if (Constants.getInstance().checkIsAudioPlay()) {
stopAudioPlaying();
refreshView();
btnPlayALL.setText(R.string.play_all);
return true;
} else {
return false;
}
return false;
}
});
}
}
In your activity's onBackPressed() method add the following:
FragmentManager fragmentManager = getSupportFragmentManager();
if (fragmentManager.getFragments().size() > 0) {
fragmentManager.popBackStack();
}else {
super.onBackPressed();
}
Also don't forget to override the onPause() method of your fragment and handle the tasks you want the fragment to finish when the back button is pressed.
When I press the back button to come back from a fragment, my activity shows a blank page.
What can I do to show the previous state of activity?
I use back stack in my project.
This is my code for pressing the back button:
public void onBackPressed()
{
if ( manager.getBackStackEntryCount() > 0 )
{
manager.popBackStack();
}
else
{
super.onBackPressed();
}
}
});
and this is for the fragment:
public void addFragmentA()
{
FragmentA a = new FragmentA();
getSupportFragmentManager().beginTransaction().replace(R.id.container, a,"fraga").addToBackStack("fraga").commit();
}
The code for the listener is:
manager.addOnBackStackChangedListener(this);
I want to work with a listener.
How can I do that?
You can use your Fragments View to move to any other Fragment or Activity.
In your Fragment.xml -> onCreateView() method
view.requestFocus();
view.setFocusableInTouchMode(true);
view.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if( keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
//Write you code here to go back to any activity or fragment
return true;
}
return false;
}
});
I'd like to use the BackButton in Fragments. I'm using this code to handle backbutton:
#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){
if (idozit.num > 0) {
if (!pmenu.pauseopen) {
pmenu.BeingPaused(idozit.idozitomegy,nextlevel,0);
} else {
pmenu.continuegame();
}
}
if (idozit.num == 0) {
idozit.numnull(db);
}
//Toast.makeText(getActivity(), "hello1", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
});
}
When I click on BackButton this code works fine BUT if click on the BackButton again the app calls the onBackPressed method from MainActivity. I don't know why but if I'm using only a Toast or Log.d something like that in the onKey method then I'm able to click it again.
I'd like to say that pmenu is a simple class which is only stops music,make things gone etc. It's seems like somehow I always stuck in that class .
Have you any idea what am I doing wrong?
A cleaner solution is to make an Interface implemented by every fragment with a method called onBackPressed() like this:
public interface FragmentInterface {
void onBackPressed();
}
Then, you override the onBackPressed in yout activity calling your current fragment's onBackPressed (I'm assuming that you have a method to get your currentFragment)
#Override
public void onBackPressed(){
FragmentInterface currentfragment = getCurrentFragment();
currentfragment.onBackPressed();
}
Of course, in your fragment, implemented method should look like this:
#Override
public void onBackPressed() {
if (idozit.num > 0) {
if (!pmenu.pauseopen) {
pmenu.BeingPaused(idozit.idozitomegy,nextlevel,0);
} else {
pmenu.continuegame();
}
}
if (idozit.num == 0) {
idozit.numnull(db);
}
//Toast.makeText(getActivity(), "hello1", Toast.LENGTH_SHORT).show();
}
Replace false in last line with true and there's no need for return true before the last one
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);
}
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();
}
}
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
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.
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
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()
}
}
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) :-) ;-)
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
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.
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;
You can use getFragmentManager().popBackStack() in basic Fragment to go back.
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.
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);
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.
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.
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
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;
}
});
}
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();
}
}
I have this hierarchy of the views:
Activity -> ViewPager -> MyViewGroup
In MyViewGroup (and only there) I override onKeyUp event:
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Log.i(TAG, "Back");
return true;
} else {
return super.onKeyUp(keyCode, event);
}
}
But when I press "Back" key, this override is not called and the app is closed. Why?
By default, the back button finishes the activity. From the android source:
Called when the activity has detected the user's press of the back key. The default implementation simply finishes the current activity, but you can override this to do whatever you want.
public void onBackPressed() {
if (!mFragments.popBackStackImmediate()) {
finish();
}
}
If you wish to alter this behavior you have to override onBackPressed in your Activity and make it not call super. Then you can implement your own behavior.
public #Override void onBackPressed()
{
if (doSomeThingOnBackPressed) {
// do some stuff
return;
}
super.onBackPressed();
}