I've read a lot about save states and fragments, but I can't wrap my head around it.
I have a fragment that is loaded when the user signs in. The user can then choose from a variety of categories, which will replace the current fragment with a new one. In this new fragment, the user can click items in a GridView which will cause a check to appear.
When I press the back button, how would I go about saving the clicked items? onSavedInstanceState is never called, and it seems like my fragment is being created all over again when I try to navigate back.
Some code:
When the user first enters the app
// creates the home fragment
Fragment homeFragment = new HomeFragment();
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.content_frame, homeFragment);
fragmentTransaction.commit();
When the user clicks on a category
Bundle bundle = new Bundle();
bundle.putSerializable("subCategory", subCategory);
Fragment ingredientsFragment = new IngredientsFragment();
ingredientsFragment.setArguments(bundle);
FragmentTransaction fragmentTransaction =
getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, ingredientsFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
When you move From HomeFragment To IngredientsFragment you are replacing 1 fragment by another (HomeFragment By IngredientsFragment) so when you press back from IngredientsFragment then It will remove IngredientsFragment from stack also and HomeFragment is already removed and this is expected behavior.
What you can do is When you invoke IngredientsFragment Fragment then "add" it not replace and when user press back then remove IngredientsFragment from stack.
Related
i have two fragments,in first fragment i have list of invoice details with check box in list view .
i need to store the list items while back from the second fragment
1st fragment:
MakePayment debtorsAging = MakePayment.newInstance();
debtorsAging.setArguments(bundle);
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, debtorsAging,MakePayment.TAG);
fragmentTransaction.addToBackStack(PaymentCollection.class.getName());
fragmentTransaction.commit();
2nd fragment:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft=fragmentManager.beginTransaction();
ft.remove(new MakePayment());
ft.commit();
fragmentManager.popBackStackImmediate();
need to restore list of invoices with checked items on go back from makePayment fragment to paymentCollection fragment
If you back to previous activity by onBackPressed (not by transaction) i think you cant pass anythig between fragments by bundle or something. One of resolution I suggest to save id's or something to SharedPreferences before back to previous activity and restore them in first fragment
I'm trying to create artificial backstack after opening notification from notification bar.
Workflow after opening notification:
After clicking on notification Intent which opens MainActivity is fired.
After opening MainActivity I check if(getArguments != null). If it's not null I open notifications fragment and pass received notification id.
If notification if(id != -1) I open Notification fragment.
The problem is that after clicking back button I go back straight into MainActivity window skipping Notifications fragment.
I open Notifications fragment like that:
Fragment frag = new NotificationFragment();
frag.setArguments(bundle);
FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, NotificationsFragment.getInstance(null, id)).commit();
I open Notification fragment like this:
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
NotificationFragment notificationFragment = new NotificationFragment();
Bundle bundle = new Bundle();
bundle.putInt("id", getArguments().getInt("id"));
notificationFragment.setArguments(bundle);
ft.add(R.id.container, notificationFragment).addToBackStack(null).commit();
R.id.container is FrameLayout used sor showing fragments.
I'm using Support librrary.
I read that FragmentTransaction.replace() deletes all existing fragments and adds new one. And FragmentTransaction.add() adds them to activity state.
Please someone correct me what I'm doing wrong and show me right way.
Change this
Fragment frag = new NotificationFragment();
frag.setArguments(bundle);
FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, NotificationsFragment.getInstance(null, id)).commit();
to
Fragment frag = new NotificationFragment();
frag.setArguments(bundle);
FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, NotificationsFragment.getInstance(null, id)).addToBackStack(null).commit();
Basically, you are not adding Notifications Fragment to backstack, that's why when clicking back, MainActivity comes up.
In my app, my activity has a container with a fragment. When a button in that fragment is clicked, I add a new fragment to the container and add the previous fragment to the backstack.
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.primary_fragment_container, homeFragmentHandler);
fragmentTransaction.addToBackStack(folderId.toString());
fragmentTransaction.commit();
The result is that pressing back closes the top fragment and returns me to the previous fragment, which is exactly how I want it. HOWEVER there are certain elements on the fragment that should be refreshed at this point. When the user clicks back and is returned to the previous fragment, how do I know to refresh the data within that fragment? is there a method such as onResume() for this scenario?
You have to proper add fragments to backstack:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
MyFragment fragment = new MyFragment ();
transaction.replace(R.id.primary_fragment_container, fragment).addToBackStack(null).commit();
Fragment homeFragmentHandler= new Fragment();
Bundle bundle = new Bundle();
//replace this line below wth something convinient
bundle.putInt("key", value);
fragment.setArguments(bundle);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.primary_fragment_container, homeFragmentHandler);
fragmentTransaction.addToBackStack(folderId.toString());
fragmentTransaction.commit();
This will send data regarding which fragment/ activity caused the previous fragment to load. Now in its onCreate add this code to check the data in the bundle
//In the onCreate of the original fragment
Bundle bundle = this.getArguments();
if(bundle.getInt(key, defaultValue)!=null{
int myInt = bundle.getInt(key, defaultValue);
// Load the data that needs to be refreshed when original fragment is loaded from the second one
}
No else statement is needed. If the fragment is made from any other activity/ fragment then the bundle.getInt will return null and hence that code inside the statement wont be executed.
I have a main container in xml file in which i will replace the fragments depending on the button clicks.
when Activity opened i am adding fragment1 to the main container with the following code
fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.container, homeMainFragment);
fragmentTransaction.commit();
in HomeMainFragment on click of one button doing the following.
Fragment2 fragment2 = new Fragment2 ();
fragmentTranasaction.replace(R.id.container, fragment2);
fragmentTranasaction.addToBackStack(null);
fragmentTranasaction.commit();
in Fragment2 on click of another button moving to Fragment3 using the following code.
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment3 fragment3 = new Fragment3 ();
transaction.replace(R.id.container, fragment3 );
transaction.commit();
now when i click back my UI should show HomeFragment instead it showing home as well as fragment3 merged together.
Just wanted to clear on my requirement.
1.when I am viewing fragment3 and click on back i should actually see the homefragment not fragment2.
2. I am not adding fragment3 to the backstack because one of the button in fragment3 again starts fragment2 which will start fragment3. (same code shown above is used) in this case if I click on back I can see multiple instances of fragment3 which i don't need. Please help to solve this issue.
Edit 2:
These are my observations.
in step 1: container has homefragment.xml
in step 2: container replaced by fragment1..xml
in step 3: container is replaced by fragment3.xml
when i click on back container is being added with homefragment which is of transaparent background thats why fragment 3.is still visible.
is there any way when user clicks back remove the backstack and add homefragment alone?
I think this is what you have to do.
fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.container, homeMainFragment);
fragmentTransaction.commit();
in HomeMainFragment on click of one button doing the following.
Fragment2 fragment2 = new Fragment2 ();
fragmentTranasaction.replace(R.id.container, fragment2);
fragmentTranasaction.addToBackStack().commit();
in Fragment2 on click of another button moving to Fragment3 using the following code.
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment3 fragment3 = new Fragment3 ();
transaction.replace(R.id.container, fragment3 );
transaction..addToBackStack().commit();
Refer below link for more info.
http://developer.android.com/training/implementing-navigation/temporal.html#back-fragments
According to the documentation,
When there are FragmentTransaction objects on the back stack and the user presses the Back button, the FragmentManager pops the most recent transaction off the back stack and performs the reverse action (such as removing a fragment if the transaction added it).
Hope this helps.
You can try:
getFragmentManager().popBackStack();
I am using Fragment for my current application. Here I have one Fragment FA and I am navigating to the other Fragment FB and I have added FA to the backstack as I want to come to FA fragment on some event to be done in FB fragment. I have a done button in the fragment FB. On Click of that button I need to do two things in the fragment FB which are as follows :-
(a). I need to finish the current fragment FB.
(b). Secondly, I need to pass some data from FB to already existing Fragment FA as I have added it to backstack.
I have just started using Fragments and don't know much about them and I want to sort out this problem.Can anyone suggest something for this, any Help would be appreciable.
Thanks in Advance.
You can pass data from one fragment to another something like below.
Fragment fragment;
fragment = new SingleImage();
Bundle bundle = new Bundle();
bundle.putString("img",actorsList.get(position).getImage());
bundle.putString("desc",actorsList.get(position).getDesc());
fragment.setArguments(bundle);
getActivity().getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).addToBackStack( "tag" ).commit();
means you can add arguments with fragment to pass to another.
and you can get that data in another fragment using below code
Bundle bundle = this.getArguments();
if(bundle != null)
{
tvdesc.setText(bundle.getString("desc"));
img_url= bundle.getString("img");
}
Since you want only one back stack entry per Fragment, make the back state name the Fragment's class name (via getClass().getName()). Then when replacing a Fragment, use the popBackStackImmediate() method. If it returns true, it means there is an instance of the Fragment in the back stack. If not, actually execute the Fragment replacement logic.
private void replaceFragment (Fragment fragment){
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();
}
}