Back press not working inside fragment - android

Question: How do I enable my back button to return to my previous hosting activity/fragment?
Situation: My launcher activity hosts a fragment while also contains a FAB. Clicking on the FAB launches a second activity which hosts another fragment. When the latter fragment is shown, a searchView is automatically expanded with focus on it. Pressing back closes the keypad. However, pressing back again does not return me to my launcher activity.
Things I've tried:
In my hosting activity
fm.beginTransaction().add(R.id.fragment_container, fragment).addToBackStack(null).commit();
#Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//additional code
} else {
getFragmentManager().popBackStack();
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DOWN) {
return true;
}
return false;
}
In fragment
frag.getView().setFocusableInTouchMode(true);
frag.getView().setOnKeyListener( new OnKeyListener(){
#Override
public boolean onKey( View v, int keyCode, KeyEvent event ){
if( keyCode == KeyEvent.KEYCODE_BACK ){
return true;
}
return false;
}
} );
Also I've noticed that pressing the back button doesn't call either onBackPressed nor onKeyDown.

Related

Show a Blank Page on Back Pressed Button

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

Android: Detect back button release

I am able to detect when the back button is pressed by using:
#Override
public void onBackPressed() {
//Do my thing
}
But now I want to detect when the back button is released. How can I do that? I'm unable to find any method like onBackReleased() which I can override to do my thing.
There is no method that specifically detects the back button release, but you could use the onKeyDown() and onKeyUp() methods. Check to make sure the key is the back button, and do your stuff in the method. Here is something you could do:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// do your stuff for when the back button is initially pressed
return true;
} else {
return false;
}
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// do your stuff for when the back button is released
return true;
} else {
return false;
}
}
If you wanted to override the default back press, you could just use the onBackPressed() method, like so:
#Override
public void onBackPressed() {
// Prevents the user from clicking the back button and returning to the parent activity
}
These methods can be implemented directly in your class. Hope it helps!

close simple side drawer on back press

I use simple sidebar drawer and i want when user back pressed if drawer open close and when close activity finish. This library have not this function default. I use below code but not work :(
final SimpleSideDrawer mSlidingMenu = new SimpleSideDrawer( mactivity );
mSlidingMenu.setLeftBehindContentView(R.layout.sidebar);
mSlidingMenu.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
mSlidingMenu.closeLeftSide();
return true;
} else
return false;
}
});
toggleDrawer() method can be used to toggle between opening and closing of the drawer. So pair it up with onBackPressed() method to close the drawer while pressing back button.
#Override
public void onBackPressed() {
mSlidingMenu.toggleDrawer();
}
#Override
public void onBackPressed() {
if(mSlidingMenu.isClosed())
{
super.onBackPressed();
}
else
{
mSlidingMenu.closeLeftSide();
}
}

Disable Back Button press from fragment

My application has an activity with so many fragments. I want to disable the back button press in some fragment. I tried with the below code. But it doesn't work.
In the main activity:
#Override
public void onBackPressed() {
super.onBackPressed();
OrderFragment.onBackPress();
}
In the fragment,
public static void onBackPressed()
{
Log.d(TAG,"It listen");
}
I have the log message but, how can I disable the back button from my fragment.
You should keep a reference to the fragment you want to disable/handle back press event on your main activity:
class MainActivity{
OrderFragment mOrderFragment;
#Override
public void onBackPressed() {
if(mOrderFragment.isVisible())
mOrderFragment.onBackPressed();
else
super.onBackPressed();
}
}
In OrderFragment:
public void onBackPressed() {
//handle back press event
}
In your oncreateView() method you need to write this code and in KEYCODE_BACk return should true then it will stop the back button option for particular fragment
View v = inflater.inflate(R.layout.xyz, container, false);
//Back pressed Logic for fragment
v.setFocusableInTouchMode(true);
v.requestFocus();
v.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return true;
}
}
return false;
}
});
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if( keyCode == KeyEvent.KEYCODE_BACK ) {
// leave this blank in order to disable the back press
return true;
} else {
return false;
}
}
});
I think you have to Override onResume method in fragments which you need to disable the back press.Tryout the following code.
#Override
public void onResume() {
super.onResume();
this.getView().setFocusableInTouchMode(true);
this.getView().requestFocus();
this.getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return true;
}
return false;
}
});
}
Have you tried like this, Actually it works for me before.
you can set listener for Back key. if you add it, i guess it works.
youfragment.getView().setOnKeyListener( new OnKeyListener()
{
#Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
return true;
}
return false;
}
}
);
super.onBackPressed in the activity is the default implementation. Remove this if you don't want it.
I know this is an old question and because of navigation components and new ways this situation rarely occurs, still, maybe my answer helps someone.
I came across a similar situation where I needed the back button to be disabled and I couldn't change the activity as well. So in a fragment, I added this code block.
Language: Kotlin
override fun onResume() {
super.onResume()
this.requireView().isFocusableInTouchMode = true
this.requireView().requestFocus()
this.requireView().setOnKeyListener { _, keyCode, _ ->
keyCode == KeyEvent.KEYCODE_BACK
}
}
This will disable your back press on that specific fragment
#Override
public void onBackPressed() {
Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (currentFragment instanceof YourFragment) {
currentFragment.onBackPressed();
} else
super.onBackPressed();
}
override fun onBackPressed() {
val currentFragment = findNavController(R.id.nav_host_fragment).currentDestination?.id
if (currentFragment == R.id.YourFragment) {
return
}
super.onBackPressed()
If you don't want your fragment to be in the backstack you can do so, by not adding it to the backstack in the transaction. So do NOT call FragmentTransaction.addToBackStack(); on the fragments you do not want in your backstack.
onBackPressed works like this:
public void More onBackPressed() {
if (!mFragments.popBackStackImmediate()) {
finish();
}
}
Thus when you call super.onBackPressed() you pop the BackStack before finishing the activity. The best way to sort this out is to make sure you do not add the fragments to the BackStack. It is normally done like this:
fragmentTransaction.addToBackStack(TAG);
An alternative solution, but uglier since you have still useless code left, would be making onBackPressed() directly call finish() to end the activity.
I would strongly advise you not use getView().setOnKeyListener(...) since it is code smell.
Try this
public void onBackPressed() {
if (!mFragments.popBackStackImmediate()) {
finish();
}else{
super.onBackPressed();}
}

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

Categories

Resources