Always returns to main fragment onBackpressed - android

I have implemented Navigation Drawer in Activity. I have 3-4 fragments in my app.
Let's say there are 3 fragments : Fragment_1, Fragment_2, Fragment_3
When I start my app, Fragment_1 is loaded and i go to another fragments using navigation drawer.
So it's like
Fragment_1 -> Fragment_2 -> Fragment_3 -> Fragment_1 -> Fragment_3
Now, when I press back button it's like
Fragment_3 -> Fragment_1 -> Fragment_3 -> Fragment_2 -> Fragment_1
But, I want something like if wherever i am when i press back key, i
navigate back to Fragment_1 always.
I am using below code to navigate to another fragment :-
nav_menu_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
switch (position) {
case 0:
DashboardFragment dashboardFragment = new DashboardFragment();
fragmentTransaction.replace(R.id.mainContainer, dashboardFragment, dashboardFragment.getClass().getName());
break;
case 1:
ProfileFragment profileFragment = new ProfileFragment();
fragmentTransaction.replace(R.id.mainContainer, profileFragment, profileFragment.getClass().getName());
fragmentTransaction.addToBackStack(null);
break;
case 2:
ContactUsFragment contactUsFragment = new ContactUsFragment();
fragmentTransaction.replace(R.id.mainContainer, contactUsFragment, contactUsFragment.getClass().getName());
fragmentTransaction.addToBackStack(null);
break;
case 3:
AboutUsFragment aboutUsFragment = new AboutUsFragment();
fragmentTransaction.replace(R.id.mainContainer, aboutUsFragment, aboutUsFragment.getClass().getName());
fragmentTransaction.addToBackStack(null);
break;
default:
break;
}
fragmentTransaction.commit();
drawer.closeDrawer(GravityCompat.START);
}
});
Please help...

#Override
public void onBackPressed() {
if(!(getSupportFragmentManager().findFragmentById(R.id.mainContainer) instanceof DashboardFragment))
{
DashboardFragment dashboardFragment = new DashboardFragment();
fragmentTransaction.replace(R.id.mainContainer, dashboardFragment, dashboardFragment.getClass().getName());
}else {
super.onBackPressed();
}
}
Use this method into main activity will solve your problem.

I've changed next lines in your code and it worked just fine
Replace:
fragmentTransaction.replace(R.id.mainContainer, dashboardFragment,
dashboardFragment.getClass().getName());
With:
getSupportFragmentManager().beginTransaction().replace(R.id.mainContainer,
dashboardFragment).commit();

Related

Back Navigation in Android

I am beginner in android and trying to develop an android app in which I stuck in back navigation. My issue is :
How to manage backstack with activities and fragments.
A1 activity with frag1 calls A2 activity and A2 activity displays a user list where on click of a list to check user profile, call to A1 Activity with Frag 2.
On opening of Frag2 of A1 activity, We are using intent flag: flag_activity_reorder_to_front and adding frag1 to backstack with FragmentManager transaction
Now IF I click on back then It shows A1 Activity with frag1 instead of A2 Activity.
IF I don't add frag1 into backstack then on back, It works with first back but on second back it exits from the app.
Any suggestions?
Try using single activity and handle all fragment transactions in it using an interface. Activity should implement this interface.
Example:
public interface FragChanger {
int NEXT_FRAGHELLO =1;
int NEXT_FRAGSET = 2;
int NEXT_FRAGSELECT =3;
int NEXT_FRAGLOG=4;
int NEXT_FRAGCHAT=5;
void onFragmentChange(int nextFrag);
}
The following should be in Your activity:
#Override
public void onFragmentChange(int nextFrag) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
switch (nextFrag){
case NEXT_FRAGHELLO:
break;
case NEXT_FRAGSET:
FragSet fragSet = new FragSet();
ft.replace(containerId,fragSet,"fragset");
ft.addToBackStack(null);
ft.commit();
break;
case NEXT_FRAGSELECT:
FragSelect fragSelect = new FragSelect();
ft.replace(containerId,fragSelect,"fragselect");
ft.addToBackStack(null);
ft.commit();
break;
case NEXT_FRAGCHAT:
FragChat fragChat = new FragChat();
ft.replace(containerId,fragChat,"fragchat");
ft.addToBackStack(null);
ft.commit();}
break;
case NEXT_FRAGLOG:
ft.replace(containerId,fragLog,"fraglog");
ft.addToBackStack(null);
ft.commit();
break;
}
Handling back in your activity:
#Override
public void onBackPressed() {
Log.d(TAG,"button back pressed");
//Check which fragment is displayed an do whatever you need
//for example like this
if (getSupportFragmentManager().findFragmentById(containerId) instanceof FragLog){
Fragment fl = getSupportFragmentManager().findFragmentByTag("fraglog");
if (fl !=null){
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.remove(fl);
ft.commit();
return;
}
}
}
Of course, this is only an example, but may be useful in Your case

NavigationDrawerFragment onbackpressed issue in fragment

My Menu have following options
fragment A
fragment B
fragment c
My fragments
fragment A----subfrag1---subfrag2
fragment B----subfrag1---subfrag2
fragment c(no sub fragments)
onBack works perfectly in following order
fragment A----subfrag1---subfrag2 reverse onback pressed.
but problem is
when am go to fragment A-->B
1 time press onback shows whitescreen only
2 times press onback then only shows fragment A.
my code is
public void onNavigationDrawerItemSelected(int position) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, PlaceholderFragment.newInstance(position+1)).addToBackStack(null)
.commit();
}
public void onSectionAttached(int number) {
Bundle bundle = new Bundle();
switch (number) {
case 1:
mTitle = " fragmentA";
fragment = new fragmentA();
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).addToBackStack(null).commit();
break;
case 2:
mTitle = " fragmentB";
fragment = new fragmentB();
final String sid="Active";
bundle.putString("id", sid);
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).addToBackStack(null).commit();
break;
case 3:
mTitle =" fragmentC";
fragment = new fragmentC();
bundle.putString("crmadminid", crmadminid);
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).addToBackStack(null).commit();
break;
}
}
onBackPressed code
#Override
public void onBackPressed() {
int count = getSupportFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//additional code
} else {
getSupportFragmentManager().popBackStack();
}
}
How to avoid 2 times press onback button issue?
I think when you press the back button on fragment B it shows white screen because the fragment is detached , I think the only work around for you is to do some thing like
fragTran.replace(R.id.content_frame, secondFrag);
fragTran.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragTran.addToBackStack("TAG");
fragTran.commit();
I think you need to remove .addToBackStack(null) from your code while going from Fragment A to B
Please try this and let me know, it it does help , mark it as answer if not then tell me so that I can update my answer

Handling fragment backstack in Navigation drawer

okay i know there are other questions that on first glance make this one look like a duplicate, but none of these answers work in my case,
What i want is the first fragment displayed to be like a Main Activity in respect to how the back button works, i need whichever fragment i choose from my navigation drawer to go back to the first fragment when the back button is pressed then a user would quit the app by pressing it again.
So ive tried using addToBackStack and when i move to another fragment if i press the back button it comes back to my first fragment (exactly as i want) but pressing the back button again leaves me with a white screen (i wonder if this is due to the transaction animation im using which ive included below) so to get around this i tried overriding the back button and throwing in a call to finish(); but this causes whichever fragment im in to finish instead of going back to the first fragment, ive tried a handful of workarounds from the above mentioned link and many others but cannot find a decent fix any suggestions?
here is my Main Activity displayView
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new FirstFragment();
break;
case 1:
fragment = new glideFrag();
break;
case 2:
fragment = new secondGlideFrag();
break;
case 3:
fragment = new thirdGlideFrag();
break;
case 4:
fragment = new forthGlideFrag();
break;
case 5:
fragment = new lgFrag();
break;
case 6:
fragment = new cyanFrag();
break;
case 7:
fragment = new sonyFrag();
break;
case 8:
fragment = new SecondFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.enter,R.anim.exit,R.anim.pop_enter,R.anim.pop_exit);
//fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.frame_container, fragment).addToBackStack("first Fragment").commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
i found this that looks like a great way around it
private boolean popNext = false;
if(popNext){
if(position == INITIAL_POSITION){
onBackPressed();
mDrawerLayout.closeDrawer(mDrawerList);
popNext = false;
return;
}
getSupportFragmentManager().popBackStackImmediate();
}
else{
if(position == INITIAL_POSITION){
mDrawerLayout.closeDrawer(mDrawerList);
return;
}
popNext=true;
}
but im still fairly new to android and im not sure what to set INITIAL_POSITION to, I tried
private static final INITIAL_POSITION = 0;
but without any luck
When adding the initial fragment, you must not add it to the back stack.
You must only do it for the next ones. When the back stack will be empty, the Activity will just finish.
Edit: Here is an explanation of the problem so you can figure out how to fix it:
Each time you add a fragment transaction to the back stack, you allow the user to revert it by pressing the back button and the Activity will return to the state it was before the transaction. If the initial fragment is added to the back stack, then when the user press back, the screen becomes blank, because there was nothing displayed before you added the initial fragment. That's why the initial fragment transaction which adds the first visible fragment to your Activity must not be added to the back stack. Usually you initialize the initial fragment like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState == null) {
Fragment fragment = new FirstFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.frame_container, fragment)
.commit();
}
}
BladeCoders answer was more trying to tell me how the backstack works rather than answering my question, i ended up not adding any fragments to the back stack, .addToBackStack(null), and overriding back button in MainActivity, feels like a little bit of a hack but works perfectly
#Override
public void onBackPressed() {
FragmentManager fragmentManager = getSupportFragmentManager();
if (fragmentManager.getBackStackEntryCount() < 1){
Fragment fragment = new FirstFragment();
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.enter, R.anim.exit,
R.anim.pop_enter, R.anim.pop_exit);
getSupportActionBar().setTitle(mDrawerTitle);
fragmentTransaction.replace(R.id.frame_container,
fragment).addToBackStack("first").commit();
}else{
finish();
}
}
You can do it even with out backstack its just my point of view to simplify so that it can help some one.
#Override
public void onBackPressed(){
Fragment f = getSupportFragmentManager().findFragmentById(R.id.container_body);
if(f.getClass().getName().equals(HomeFragment.class.getName())){ // here HomeFragment.class.getName() means from which faragment you actually want to exit
finish();
}else{
displayView(0); //were you want to go when back button is pressed
}
}
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment = new HomeFragment();
title = getString(R.string.app_name);
break;
case 1:
fragment = new OffersFragment();
title = getString(R.string.nav_item_offers);
break;
case 2:
fragment = new NotificationFragment();
title = getString(R.string.nav_item_notifications);
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.commit();
// set the toolbar title
getSupportActionBar().setTitle(title);
}
}

How can i get the current Fragment ID

I did a navigation drawer, and I’ve set some items and normally when I select an item the current fragment will be changed by a new one, it's not the case for me, the first Activity still displayed even if the fragments change. This is my onNavigationDrawerItemSelectedmethod and it's clear I change the fragment every time i click on a new one.
#Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getSupportFragmentManager();
// TODO : Added
switch(position) {
/*case 0 :
fragmentManager.beginTransaction()
.replace(R.id.container, new ProfilFrgement())
.commit();
break;*/
case 1:
fragmentManager.beginTransaction()
.replace(R.id.container, new SpotFragement())
.commit();
break;
case 2:
fragmentManager.beginTransaction()
.replace(R.id.container, new SessionsFragement())
.commit();
break;
/*case 3:
fragmentManager.beginTransaction()
.replace(R.id.container, new EventsFragment())
.commit();
break;*/
}
}
I think my problem is a change always the same container. So what I need its getting the current fragment ID
Sorry for too late but I have a solution to get fragment ID. You can use name of Fragment Class as an Identifier not the ID. Use a static String variable to store class name.
public class Activity{
...
static String currentFragment = null;
...
...
#Override
public boolean onNavigationItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_one:
setFragment(new oneFragment());
break;
case R.id.nav_two:
setFragment(new twoFragment());
break;
}
return true;
}
public static void setFragment(#NonNull Fragment f) {
if(!f.getClass().getName().equals(currentFragment)){
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container, f);
fragmentTransaction.commit();
currentFragment = f.getClass().getName();
}
...
}
What is current fragment ID here? Ur id is R.id.container which is only one rt? then what is the question about "How can i get the current Fragment ID"?
If question is to find which is the current fragment is shown to user? If yes then
Fragment ft = getSupportFragmentManager().findFragmentById(R.id.container);
if (ft instanceof SpotFragement) {
// navigation drawer item 1 and current fragment is SpotFragment.
} else if (ft instanceof SessionsFragement) {
}
Make sure that your container styling is correct.
Check following values of container once -
android:layout_width
android:layout_height

Back button closing app even when using FragmentTransaction.addToBackStack()

None of the other questions I have read on stackoverflow have been able to help with my problem. As far as I can tell, I am doing everything correctly.
I have a master/detail flow with fragments.
Upon creation of the main activity, the master fragment is loaded with the following code:
Fragment frag;
frag = new MainListFragment();//<-- **the master fragment**
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.fragment_container, frag);
Log.d("My Debug Bitches", "stack:" + fm.getBackStackEntryCount());
transaction.commit();
The master fragment has a ListView; clicking on a list item brings up the details fragment like so:
#Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
SubListFragment frag = new SubListFragment();//<-- **the detail fragment**
transaction.replace(R.id.fragment_container, frag);
transaction.addToBackStack(null);
transaction.commit();
fm.executePendingTransactions();
Log.d("My Debug Bitches", "stack:" + fm.getBackStackEntryCount());
}
Now, according to LogCat, the BackStackEntryCount changes from 0 to 1 after I navigate from master fragment to detail fragment:
So why is it that, when I click the back button while in the details fragment, that the app closes instead of returning to the master fragment??????????
You have to add the popBackStack() call to the onBackPressed() method of the activity.
Ex:
#Override
public void onBackPressed() {
if (fragmentManager.getBackStackEntryCount() > 0) {
fragmentManager.popBackStack();
} else {
super.onBackPressed();
}
}
#Bobbake4's answer is awesome, but there is one little problem.
Let's say I have three fragments A, B and C.
A is the main Fragment (the fragment that shows when I launch my app), B and C are fragments I can navigate to from the navigation drawer or from A.
Now, when I use the back button from B or C, I go back to the previous fragment (A) alright, but the title of the previous fragment (fragment B or C) now shows in the actionBar title of Fragment A. I have to press the back button again to "truly" complete the back navigation (to display the view and correct title for the fragment and returning to)
This is how I solved this problem. Declare these variables.
public static boolean IS_FRAG_A_SHOWN = false;
public static boolean IS_FRAG_B_SHOWN = false;
public static boolean IS_FRAG_C_SHOWN = false;
In the MainActivity of my app where am handling navigation drawer methods, I have a method displayView(position) which handles switching of my fragments.
private void displayView(int position) {
IS_FRAG_A_SHOWN = false;
IS_FRAG_B_SHOWN = false;
IS_FRAG_C_SHOWN = false;
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new FragmentA();
IS_FRAG_A_SHOWN = true;
break;
case 1:
fragment = new FragmentB();
IS_FRAG_B_SHOWN = true;
break;
case 2:
fragment = new FragmentC();
IS_FRAG_C_SHOWN = true;
break;
default:
break;
}
finally, in my onBackPressed method, I do this:
public void onBackPressed() {
if(fragmentManager.getBackStackEntryCount() != 0) {
fragmentManager.popBackStack();
if (IS_FRAG_A_SHOWN) { //If we are in fragment A when we press the back button, finish is called to exit
finish();
} else {
displayView(0); //else, switch to fragment A
}
} else {
super.onBackPressed();
}
}

Categories

Resources