My app exits when i try to move from child fragment to parent fragment(it doesn't crashes).Here LandingActivity.java is main activity in which I am calling fragment ChannelGrid.java which calls fragment GridMain.java.When i presses back button of mobile in fragment GridMain app exits rather than moving to ChannelGrid.java.I have added addToBackStack("tag") to fragments and also tried using onKey()..I tested my app on different devices also..I checked out other solutions with same issue and tried them but nothing works..
Navigation Drawer-LandingActivity.java-ChaanelGrid.java(Fragment)-GridMain.java(Fragment)
LandingActivity.java
currentFragment = new ChaanelGrid();
currentFragment.setArguments(args);
frgManager = getFragmentManager();
frgManager.beginTransaction().add(R.id.content_frame, currentFragment).addToBackStack("tag")
.commit();
ChaanelGrid.java
Fragment currentFragment = new GridMain();
FragmentManager frgManager;
frgManager = getFragmentManager();
frgManager.beginTransaction().add(R.id.content_frame, currentFragment).addToBackStack("GridMain")
.commit()
GridMain.java(i tried without onKey() method also but didn't worked)
rootView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK)
{
Fragment currentFragment = new ChaanelGrid();
FragmentManager frgManager;
frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, currentFragment)
.commit();
return true;
}
logcat verbose
10-31 21:46:57.954 24452-24452/D/ActivityThread﹕ ACT-AM_ON_PAUSE_CALLED ActivityRecord{41eb8b98 token=android.os.BinderProxy@41bb9828 {xyz/xyz..activity.LandingActivity_}}
10-31 21:46:57.971 24452-24452/ D/ActivityThread﹕ ACT-PAUSE_ACTIVITY_FINISHING handled : 0 / android.os.BinderProxy@41bb9828
10-31 21:46:58.007 24452-24452/ V/InputMethodManager﹕ focusOut: android.widget.GridView@41f06f40 mServedView=android.widget.GridView@41f06f40 winFocus=false
10-31 21:46:58.297 24452-24452/ I/SurfaceTextureClient﹕ [0x5143bc58] frames:44, duration:1.002000, fps:43.883736
10-31 21:46:58.350 24452-24452/ D/OpenGLRenderer﹕ Flushing caches (mode 0)
10-31 21:46:58.432 24452-24452/ D/OpenGLRenderer﹕ Flushing caches (mode 0)
10-31 21:46:58.753 24452-24452/ D/OpenGLRenderer﹕ Flushing caches (mode 0)
10-31 21:46:58.754 24452-24452/ D/OpenGLRenderer﹕ Flushing caches (mode 0)
10-31 21:46:58.755 24452-24452/ D/OpenGLRenderer﹕ Flushing caches (mode 2)
10-31 21:46:58.879 24452-24452/ D/ActivityThread﹕ ACT-DESTROY_ACTIVITY handled : 1 / android.os.BinderProxy@41bb9828
I tried adding following in LandingActivity.java
@Override
public void onBackPressed() {
FragmentManager frgManager;
frgManager = getFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag("GridMain");
if (fragment != null) {
GridMain gridMain = (GridMain) fragment;
if (!gridMain.onBackPressed()) {
super.onBackPressed();
}
}
else {
super.onBackPressed();
}
}
and following in GridMain.java
protected boolean onBackPressed() {
FragmentManager frgManager;
frgManager = getFragmentManager();
frgManager.popBackStack();
return true;
}
Using Log i checked tht onBackPressed() of LandingActivity.java is being called but still the same output..
How do I get rid of current fragment navigation component? You add to the back state from the FragmentTransaction and remove from the backstack using FragmentManager pop methods: FragmentManager manager = getActivity(). getSupportFragmentManager();
In order to check when the 'BACK' button is pressed, use onBackPressed() method from the Android library. Next, perform a check to see if the 'BACK' button is pressed again within 2 seconds and will close the app if it is so. Otherwise, don't exit.
Use replace() to replace an existing fragment in a container with an instance of a new fragment class that you provide. Calling replace() is equivalent to calling remove() with a fragment in a container and adding a new fragment to that same container. transaction. commit();
This is how I solved it..When you press back button inside your fragment onBackPressed() method of your activity will be called if you have declared that..So handling back button for fragments within navigation drawer can be one in this way..
MainActvity
public static boolean isMainActivityShown ;
public static boolean isFragment1Shown=false ;
public static boolean isFragment2Shown=false ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isMainActivityShown=true //inside onCreate method put isMainActivityShown true
.
.
.
{
Fragment currentFragment = new Fragment1();
isMainActivityShown=false; //when moving to fragment1
isFragment1Shown=true;
frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, currentFragment)
.commit();
}
.
.
}
@Override
public void onBackPressed() {
if(isMainActivityShown)
{
finish();
}
else if(isFragment1Shown)
{
//write the code to handle back button when you are in Fragment1
}
else if(isFragment2Shown)
{ //When you are in Fragment 2 pressing back button will move to fragment1
Fragment currentFragment = new Fragment1();
isFragment2Shown=false;
isFragment1Shown=true;
FragmentManager frgManager;
frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, currentFragment)
.commit();
}
}
Fragment1
Fragment currentFragment = new Fragment2();
MainActivity.isFragment1Shown=false;
MainActivity.isFragment2Shown=true;
frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, currentFragment)
.commit();
This is how I normally handle the Back Button:
// "State Machine" variables: to indicate which is the active Fragment.
private static boolean isHelpShown = false;
protected static boolean isInfoShown = false;
protected static boolean isMainShown = false;
private static boolean isViewShown = false;
// Used to switch between Fragments.
private static enum Fragments
{
MAIN,
VIEW,
HELP,
INFO
}
@Override
public final void onBackPressed()
{
if (isMainShown)
{
// We're in the MAIN Fragment.
finish();
}
else
{
// We're somewhere else, reload the MAIN Fragment.
showFragment(Fragments.MAIN);
}
}
private final void showFragment(final Fragments FragmentType)
{
isViewShown = false;
isHelpShown = false;
isInfoShown = false;
isMainShown = false;
final FragmentTransaction ft =
getSupportFragmentManager().beginTransaction();
/*
Replace whatever is in the fragment_container view with this
fragment, and add the transaction to the back stack so the user can
navigate back.
*/
switch(FragmentType)
{
case HELP:
{
ft.replace(R.id.frgMaster, new FRG_Help());
isHelpShown = true;
break;
}
case INFO:
{
ft.replace(R.id.frgMaster, new FRG_Info());
isInfoShown = true;
break;
}
case VIEW:
{
ft.replace(R.id.frgMaster, new FRG_View());
isViewShown = true;
break;
}
case MAIN:
{
ft.replace(R.id.frgMaster, new FRG_Main());
isMainShown = true;
break;
}
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// Finalize the transaction...
ft.commit();
getSupportFragmentManager().executePendingTransactions();
}
As you can see, for my needs I only handle when we're in the MAIN Fragment (I quit) or when we aren't (I go back to the MAIN Fragment: another Back press and it quits).
You can add more checks in the onBackPressed method to check if you are in another Fragment and load another one, accordingly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With