I've tried almost everything but nothing seems to work. I have a navigation drawer with these fragments, say:
A - viewpager
B - listview
C - listview
Now in B and C, listview are clickable items with each having their own fragments. So ListViewA has a fragment, ListViewB has a fragment.
I want proper back navigation. This is how I'm doing it, when initializing the navigation drawer:
Fragment fragment = getHomeFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.fade_in,
android.R.anim.fade_out);
fragmentTransaction.replace(R.id.frame, fragment, CURRENT_TAG);
fragmentTransaction.commit();
And when choosing an option from listview:
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.anim.fade_in,
android.R.anim.fade_out);
ft.replace(R.id.frame, new FragmentB(),"HubSettings");
ft.addToBackStack(null);
ft.commit();
If I put addtoBackStack() in both transactions, back navigation works fine but navigation drawer title is not being set properly. I want to disable back button and force changing fragments from navigation drawer so that action bar title is set properly. How do I disable back button when it comes to CFragment?
One can go from menu like:
Navigation Drawer->B Fragment->Listview option 1 Fragment
Pressing Back -> Back to B Fragment -> Disable Back Button
Just override onBackPressed in your Activity which contains the fragments like this:
#Override
public void onBackPressed() {
int count = getSupportFragmentManager().getBackStackEntryCount();
if (count > 0) {
getSupportFragmentManager().popBackStack();
updateDrawerToggle();
}
}
Related
My application contains AppBaseActivity having NavigationView with few menu items. By default, I load Home fragment & on clicking each menu item from drawer, I open specific fragment.
My problem is, I need keep Home fragment all the time showing if user clicks back button.
Stepwise explanation :
On activity launch, loads Home fragment by default
Suppose selects Menu Item 1, loads related fragment[*4]
Suppose selects Menu Item 2, loads related fragment[*4]
I want to make back stack clear however, keeping Home fragment persistent so that if user presses back button instead of opting menu item from drawer or simply go to any fragment & on killing it, should navigate back to Home fragment.
In my current case, it simply closes/terminates my app.
AppBaseActivity Java (some part of code)
onCreate() {
fragmentTransaction = fragmentManager.beginTransaction();
HomeFragment homeFragment = new HomeFragment();
fragmentTransaction.add(R.id.body_container, homeFragment, getResources().getString(R.string.app_name));
fragmentTransaction.commit();
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
navigationView.getMenu().findItem(item.getItemId()).setChecked(true);
switch (item.getItemId()) {
case R.id.nav_terms :
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentTransaction = fragmentManager.beginTransaction();
TCFragment tcFragment = new TCFragment();
fragmentTransaction.add(R.id.body_container, tcFragment, getResources().getString(R.string.tc_screen_name));
fragmentTransaction.commit();
break;
case R.id.nav_about_us :
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentTransaction = fragmentManager.beginTransaction();
AboutUsFragment aboutUsFragment = new AboutUsFragment();
fragmentTransaction.add(R.id.body_container, aboutUsFragment, getResources().getString(R.string.about_us_screen_name));
fragmentTransaction.commit();
break;
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
try by adding this line with home fragment before commit:
fragmentTransaction addTobackStack(null);
You need to add the transaction to the backstack using addToBackStack(). The back press would automatically pop the topmost fragment from the backstack.
Refer to
https://developer.android.com/guide/components/fragments.html
The relevant section is "Performing Fragment Transactions"
I am using navigation drawer and fragment to show the component on selecting navigation option.And if user select navigation drawer option a fragment will open. So my problem is when I call a activity from fragment and when I press back button it call previous fragment but the content of that fragment remain same. What I want is when I press back button from activity it should open my fragment or recall fragment and values should be blank like first time we call the fragment.
Thanks.
Try this:-
#Override
public void onBackPressed() {
if (getTitle().equals("Title")) {
YourFragment fragment =new YourFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
} else {
super.onBackPressed();
}
}
My activity consists of navigation drawer and currently have 5 options in the left menu. Which all opens in fragment.
I am looking for a way to keep a stack of all the fragments so when the user presses back button he moves to previous fragment.
Like- Activity consists of drawer menu which have 5 options menu1, menu2, menu3, menu4, menu5 having corresponding fragments F1, F2, F3, F4, F5.
User presses menu1 he is forwarded to F1
Then presses menu2, and then menu4.
When the user is at F4 and he presses back he should be moved to F2 rather than exiting the activity or app.
How can it implemented and example or sample code preferred.
I currently use this code but it does not help me out
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment)
.addToBackStack(null)
.commit();
I found some workaround for your query :
Override onBackPressed() in code
Use methods related to backstack maintained which contains your all fragment transactions
public void onBackPressed(){
FragmentManager fm = getFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
Log.i("MainActivity", "popping backstack");
fm.popBackStack(); // this will display last visible fragment
getActinBar().setTitle(mTitle); // save your title in some variable and restore here
} else {
Log.i("MainActivity", "nothing on backstack, calling super");
super.onBackPressed(); // system will handle back key itself
}
}
Reference answer : this
I used to replace Fragment like as below :
public void replaceFragment(Fragment fragment, boolean addToBackStack, int transition) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.activity_main_relative_container, fragment, fragment.getClass().getName());
ft.setTransition(transition);
if (addToBackStack) {
ft.addToBackStack(fragment.getClass().getName());
}
ft.commitAllowingStateLoss();
}
// While to replace Fragment
replaceFragment(mFragment, true, FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// False for not adding Fragment in back stack and true to add.
Hope this helps.
You need to add fragment to backstack
private FragmentTransaction m_fragmentTransaction;
FragmentOne m_fragOne = new FragmentOne();
m_fragmentTransaction = m_fragmentManager.beginTransaction();
m_fragmentTransaction.replace(R.id.dl_flContainer, m_fragOne , FragmentOne.class.getSimpleName());
m_fragmentTransaction.addToBackStack(FragmentOne.class.getSimpleName());
m_fragmentTransaction.commit();
Ok i have an activity with one main fragment, that has a menu on it. When a user clicks on a menu item another fragment is animated into the screen, with this code:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out);
ft.hide(getFragmentManager().findFragmentByTag("menu_fragment"));
Fragment opisFragment = getFragmentManager().findFragmentByTag("opis_fragment");
if (opisFragment == null) {
opisFragment = new OpisFragment();
ft.add(R.id.p_container, opisFragment, "opis_fragment");
ft.commit();
} else {
ft.show(opisFragment);
}
Note: pr_fragment is the tag of the current fragment, the one that has the menu.
Now, this works well, but when i'm on the second fragment i want to add the functionality, that when the user clicks the back button it will show the first fragment. With this code, when i click back it exits the activity alltogether.
Thank you for the help!
All you need is to use addToBackStack(String name) of FragmentTransaction
// Showing menu fragment also added in backstack
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out)
.add(R.id.p_container, menuFragment, "menu_fragment")
.addToBackStack("menu_fragment")
.commit();
// Showing opis fragment also added in backstack
FragmentTransaction ft2 = getFragmentManager().beginTransaction();
ft2.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out)
.add(R.id.p_container, opisFragment, "opis_fragment")
.addToBackStack("opis_fragment")
.commit();
Assuming "opis fragment" is in foreground, when you press back button, "menu_fragment" will be displayed back to the foreground, pressing back button again will exit the activity.
With this code, when i click back it exits the activity alltogether.
Normal because there is just your activity in your app stack. the addToBackStack() method is what you are looking for.
if (opisFragment == null) {
opisFragment = new OpisFragment();
ft.add(R.id.p_container, opisFragment, "opis_fragment");
ft.addToBackStack("tag"); // <<< this line
ft.commit();
}
From the doc :
Before you call commit(), however, you might want to call addToBackStack(), in order to add the transaction to a back stack of fragment transactions. This back stack is managed by the activity and allows the user to return to the previous fragment state, by pressing the Back button.
in mainactivity you can check fragments count if fragments count more than one we will show back button
if(getSupportFragmentManager().getBackStackEntryCount() > 0)
{
mDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportActionBar().setDisplayShowHomeEnabled(false);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
else
{
mDrawerToggle.setDrawerIndicatorEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setHomeButtonEnabled(false);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
I have a header bar (kinda like menu) and 4 fragments (MAIN, A, B, C) from which the MAIN should be 'main/root' fragment for backstack.
Problem i have is when user via menu goes for example MAIN > A > B > C.
If i simply use backstack it will go in reverse order which i don't want.
I need back button to go back to MAIN no matter how user navigated to one of those 3.
My current code (which is wrong, it quits app when not in MAIN and current fragment is switched from other non-MAIN fragment) looks like this:
private void SwitchFragment(Fragment pFragment)
{
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.main_fl_fragmentcontainer, pFragment);
if (_CurrentFragment == _Frag_Main)
ft.addToBackStack(null);
ft.commit();
_CurrentFragment = pFragment;
}
Your stack must contains 2 fragments at maximum
Main is visible
Main is onBackstack / AorBorC is visible.
User click on back ==> Main is visible.
User click on back ==> application end
I suppose A / B / C are displayed in the same view so in this case,
When user click on your Menu, you have to check if A/ B / C is currently displayed and replace it by the one selected by the user.
private void displayFragment(Fragment pFragment) {
Fragment fr = getSupportFragmentManager()
.findFragmentById(R.id.main_fl_fragmentcontainer);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.main_fl_fragmentcontainer, pFragment);
if (_CurrentFragment == _Frag_Main) {
ft.addToBackStack(null);
}
ft.commit();
_CurrentFragment = pFragment;
}
can override OnBackPressed method of your activity.