Android Fragment handle back button press
When you are transitioning between Fragments, call addToBackStack()
as part of your FragmentTransaction
:
FragmentTransaction tx = fragmentManager.beginTransation();
tx.replace( R.id.fragment, new MyFragment() ).addToBackStack( "tag" ).commit();
If you require more detailed control (i.e. when some Fragments are visible, you want to suppress the back key) you can set an OnKeyListener
on the parent view of your fragment:
//You need to add the following line for this solution to work; thanks skayred
fragment.getView().setFocusableInTouchMode(true);
fragment.getView().requestFocus();
fragment.getView().setOnKeyListener( new OnKeyListener()
{
@Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
return true;
}
return false;
}
} );
How to detect when back button pressed in fragment android?
In your MainActivity
@Override
public void onBackPressed()
{
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.containerView,new Recommendation()).commit();
}
Handle back pressed on fragment then continue navigating
You're overriding the usual back-pressed behaviour, which is why it doesn't navigate back. You need to call parentFragmentManager.popBackStack()
(or findNavController().popBackStack()
if you're using the Navigation component).
Your other option is to do setEnabled = false
in the callback after you remove your podcast (meaning the handler won't be called next time) and then immediately fire a back-pressed event with activity?.onBackPressed()
. That will handle it with the default behaviour (unless you've added more dispatchers! In which case it'll fall through to the next one)
edit: I've used the popBackStack
stuff myself, but it might be a better idea to use the "disable dispatcher and re-fire" approach in general. Purely because the standard behaviour could possibly change (a lot is going on with back stacks and navigation development) so hardcoding a popBackStack
call might lead to problems down the line.
I don't know what the official line is though - the docs have this to say:
Changing the enabled state on the
OnBackPressedCallback
is strongly recommended for temporary changes as it maintains the ordering described above, which is particularly important if you have callbacks registered on multiple different nested lifecycle owners.
but that's more about changing the response to a back press temporarily, not handling one press and messing around, firing multiple events to generate a particular standard behaviour
How to handle Back Button press in android fragments
I think you can do this:
Create a generic Fragment:
public abstract class extends BaseFragment {
public abstract boolean onBackPressed();
}
In his Fragments, extends this BaseFragment, example:
public class TopStoriesFragment extends BaseFragment {
...
@Override
public boolean onBackPressed()
{
//if you return false, then it is because you have not consumed
//the event, but if it returns true, which is consumed by this event.
return false;
}
}
In his MainActivity activity, you should check in onBackPressed event, if the event was consumed or not, to decide what to do.
It is very important that you save the current tab!
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener {
//It is very important that you save the current tab!
private BaseFragment currentTab;
// ... implementation
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int index) {
currentTab = null;
switch (index) {
case 0:
// Top Rated fragment activity
currentTab = new TopStoriesFragment();
break;
case 1:
// Games fragment activity
return new NationalFragment();
case 2:
// Movies fragment activity
currentTab = new InternationalFragment();
break;
case 3:
// Movies fragment activity
currentTab = new SportsFragment();
break;
case 4:
// Movies fragment activity
currentTab = new TechnologyFragment();
case 5:
// Movies fragment activity
currentTab = new BusinessFragment();
break;
case 6:
// Movies fragment activity
currentTab = new EntertainmentFragment();
break;
}
return currentTab;
}
@Override
public int getCount() {
// get item count - equal to number of tabs
return 7;
}
public void stop() {
// get item count - equal to number of tabs
return;
}
}
@Override
public void onBackPressed()
{
//If the event returned false, then call the super.
if(currentTab == null || !currentTab.onBackPressed())
super.onBackPressed();
}
}
Change to your case!
Handling back button in Android Navigation Component
Newest Update - April 25th, 2019
New release androidx.activity ver. 1.0.0-alpha07 brings some changes
More explanations in android official guide: Provide custom back navigation
Example:
public class MyFragment extends Fragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This callback will only be called when MyFragment is at least Started.
OnBackPressedCallback callback = new OnBackPressedCallback(true /* enabled by default */) {
@Override
public void handleOnBackPressed() {
// Handle the back button event
}
};
requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
// The callback can be enabled or disabled here or in handleOnBackPressed()
}
...
}
Old Updates
UPD: April 3rd, 2019
Now its simplified. More info here
Example:
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), this);
@Override
public boolean handleOnBackPressed() {
//Do your job here
//use next line if you just need navigate up
//NavHostFragment.findNavController(this).navigateUp();
//Log.e(getClass().getSimpleName(), "handleOnBackPressed");
return true;
}
Deprecated (since Version 1.0.0-alpha06
April 3rd, 2019) :
Since this, it can be implemented just using JetPack implementation OnBackPressedCallback
in your fragment
and add it to activity:getActivity().addOnBackPressedCallback(getViewLifecycleOwner(),this);
Your fragment should looks like this:
public MyFragment extends Fragment implements OnBackPressedCallback {
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getActivity().addOnBackPressedCallback(getViewLifecycleOwner(),this);
}
@Override
public boolean handleOnBackPressed() {
//Do your job here
//use next line if you just need navigate up
//NavHostFragment.findNavController(this).navigateUp();
//Log.e(getClass().getSimpleName(), "handleOnBackPressed");
return true;
}
@Override
public void onDestroyView() {
super.onDestroyView();
getActivity().removeOnBackPressedCallback(this);
}
}
UPD:
Your activity should extends AppCompatActivity
or FragmentActivity
and in Gradle file:
implementation 'androidx.appcompat:appcompat:{lastVersion}'
Fragment pressing back button
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()
}
}
Related Topics
Save Arraylist to Sharedpreferences
Firebase Offline Capabilities and Addlistenerforsinglevalueevent
How to Determine When Fragment Becomes Visible in Viewpager
Changing Locale Within the App Itself
Android Accelerometer Accuracy (Inertial Navigation)
How to Display an Alert Dialog on Android
Handle Textview Link Click in My Android App
Drawing a Line/Path on Google Maps
Android Broadcastreceiver on Startup - Keep Running When Activity Is in Background
How to Remove All Debug Logging Calls Before Building the Release Version of an Android App
Getapplication() Vs. Getapplicationcontext()
Changing API Level Android Studio
How to Create an Object of an Activity in Other Class
How to Convert a Base64 String into a Bitmap Image to Show It in a Imageview