How to implement onBackPressed() in Fragments?
Is there a way in which we can implement onBackPressed()
in Android Fragment similar to the way in which we implement in Android Activity?
As the Fragment lifecycle do not have onBackPressed()
. Is there any other alternative method to over ride onBackPressed()
in Android 3.0 fragments?
Solution 1:
I solved in this way override onBackPressed
in the Activity. All the FragmentTransaction
are addToBackStack
before commit:
@Override
public void onBackPressed() {
int count = getSupportFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//additional code
} else {
getSupportFragmentManager().popBackStack();
}
}
Solution 2:
In my opinion the best solution is:
JAVA SOLUTION
Create simple interface :
public interface IOnBackPressed {
/**
* If you return true the back press will not be taken into account, otherwise the activity will act naturally
* @return true if your processing has priority if not false
*/
boolean onBackPressed();
}
And in your Activity
public class MyActivity extends Activity {
@Override public void onBackPressed() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_container);
if (!(fragment instanceof IOnBackPressed) || !((IOnBackPressed) fragment).onBackPressed()) {
super.onBackPressed();
}
} ...
}
Finally in your Fragment:
public class MyFragment extends Fragment implements IOnBackPressed{
@Override
public boolean onBackPressed() {
if (myCondition) {
//action not popBackStack
return true;
} else {
return false;
}
}
}
KOTLIN SOLUTION
1 - Create Interface
interface IOnBackPressed {
fun onBackPressed(): Boolean
}
2 - Prepare your Activity
class MyActivity : AppCompatActivity() {
override fun onBackPressed() {
val fragment =
this.supportFragmentManager.findFragmentById(R.id.main_container)
(fragment as? IOnBackPressed)?.onBackPressed()?.not()?.let {
super.onBackPressed()
}
}
}
3 - Implement in your target Fragment
class MyFragment : Fragment(), IOnBackPressed {
override fun onBackPressed(): Boolean {
return if (myCondition) {
//action not popBackStack
true
} else {
false
}
}
}
Solution 3:
If you're using androidx.appcompat:appcompat:1.1.0
or above then you can add an OnBackPressedCallback
to your fragment as follows
requireActivity()
.onBackPressedDispatcher
.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
Log.d(TAG, "Fragment back pressed invoked")
// Do custom work here
// if you want onBackPressed() to be called as normal afterwards
if (isEnabled) {
isEnabled = false
requireActivity().onBackPressed()
}
}
}
)
See https://developer.android.com/guide/navigation/navigation-custom-back
Solution 4:
According to @HaMMeRed answer here is pseudocode how should it works.
Lets say that your main activity is called BaseActivity
which has child fragments (like in SlidingMenu lib example).
Here are the steps:
First we need create interface and class which implements its interface to have generic method
-
Create class interface
OnBackPressedListener
public interface OnBackPressedListener { public void doBack(); }
-
Create class which implements skills of
OnBackPressedListener
public class BaseBackPressedListener implements OnBackPressedListener { private final FragmentActivity activity; public BaseBackPressedListener(FragmentActivity activity) { this.activity = activity; } @Override public void doBack() { activity.getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); } }
Since now, we will work on our code
BaseActivity
and its fragments-
Create private listener on top of your class
BaseActivity
protected OnBackPressedListener onBackPressedListener;
-
create method to set listener in
BaseActivity
public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) { this.onBackPressedListener = onBackPressedListener; }
-
in override
onBackPressed
implement something like that@Override public void onBackPressed() { if (onBackPressedListener != null) onBackPressedListener.doBack(); else super.onBackPressed();
-
in your fragment in
onCreateView
you should add our listener@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { activity = getActivity(); ((BaseActivity)activity).setOnBackPressedListener(new BaseBackPressedListener(activity)); View view = ... ; //stuff with view return view; }
Voila, now when you click back in fragment you should catch your custom on back method.