How to implement unlimited fragment stack in android like Facebook application where you navigate from one profile to another and when you press the back button it navigates back to each profile you visited.
What you need is adding each new fragment you created to backstack as following, and then when you press back on new fragments, you just need to pop it from stack:
Fragment fragment = new YourFragmentGoesHere();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment)
.addToBackStack("Your Pre-defined String name for related fragment").commit();
And when you press back in new fragment you go backwards with following :
FragmentManager fm = getFragmentManager();
fm.popBackStack("Your pre-defined string name for fragment", FragmentManager.POP_BACK_STACK_INCLUSIVE);
That's it basically.
It seems that you're looking for implementing an unlimited back stack for fragments in Android. What you really want to do is first read this page:
Providing Proper Back Navigation
Pay particular attention to the "Implement Back Navigation for Fragments" section. I could just repeat all the information here, but I'll instead specify that yes, this is technically unlimited, in the same sense Facebook's back button functionality is unlimited (ie, limited by free memory).
As another note, pay careful attention if different fragments change the UI in certain ways, as the standard back navigation for fragments just reverses the exact fragment transaction you had. If you run into issues, make sure to properly override the onBackPressed method and/or try to add/remove/replace fragments differently (ex: this question here).
Related
Fragments is something that I am still trying to understand, I get some of it but not all of it.
My question is, do i need a container to start a new fragment instance?
This is what I have been currently doing to launch a fragment from my current activity that i have a container in.
FragmentManager fm = getActivity().getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(container.getId(), new OtherFragment());
ft.commit();
So my main activity has a container where I can switch from 4 fragments. Now lets say I click on one of the list items in my 3rd tab. That launches a new activity that shows another listview. Then if i click on the item on that listview, i launch a new activity. Then, were it says "tap for more information", I will be launching a new activity (I haven't created this yet, and that is why I am asking this).
But I feel like it could just be launching fragments instead of activities. If so, how do I go about doing that, because I feel like I need some type of container to put it in since I have tried launching a newinstance of a dummy fragment class i created it but it doesn't launch. If not, how do i just create a new instance of it without a container, if possible.
Or do I only use fragments whenever they will be similar and will have a container to be put in??
And I could do fragmentActivity, but that is almost the same as Activity. The reason I ask is because we shouldn't have so many activities, right? or does having as many as activities as you want not affect the project performance? Because right now I usually create activities for everything, unless its like the first picture where I will have something similar that can be put into a container.
Thanks.
You're going to to pretty much the same thing that you did to show the first fragment.
FragmentManager fm = getActivity().getFragmentManager();
if (mDetailFragment == null)
{
mDetailFragment = new DetailFragment();
}
FragmentTransaction ft = fm.beginTransaction();
ft.replace(container.getId(), mDetailFragment);
ft.commit();
You're going to want to keep references to your fragments so you're not creating them new every time. To improve the user experience you can add animations to the transition and, if it makes sense, add the fragment to the backstack.
ft.addToBackstack("OtherFragment");
ft.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.popEnter, R.anim.popExit);
My Application has one Activity with a layout (FrameLayout) for many fragments.
At the start of the Application it displays a list of Places (PlacesFragment).
When a Place is clicked, a Fragment that displays a list of cams (CamFragment) is added. Inside this fragment there is also a button "info".
When the user press the "info" button a new fragment (InfoPlaceFragment) that displays information about the place, is added.
Here is a graphical explanation:
I want to be able to go back to "CamFragment(B)" from "InfoPlaceFragment(C)", and to go back to "PlacesFragment(A)" from "CamFragment(B)".
One Question:
1) Is it possible to realize this or an alternative solution is better?
------- EDIT -------
SOLUTION:
In the "MainActivity.java":
onPlaceParse() // This method is called when the data from the server is received:
// Here I create the "PlaceFragment"
fManager = getSupportFragmentManager();
fragmentPlaces = new PlacesFragment();
fManager.beginTransaction()
.replace(R.id.fragment_list_container, fragmentPlaces)
.commit();
onResortSelected // This method is called when the resort is selected
fragmentCams = new CamsFragment();
fManager.beginTransaction()
.replace(R.id.fragment_list_container, fragmentCams)
.addToBackStack(null)
.commit();
onButtonInfoSelected // This method is called when the btn info is selected
fragmentInfo = new InfoResortFragment();
fManager = getSupportFragmentManager();
fManager.beginTransaction()
.replace(R.id.fragment_list_container, fragmentInfo, "Info")
.addToBackStack(null)
.commit();
When you press the back button, if you are in the "Info Fragment" it returns to "PlaceFragment" and if you are in the "CamsFragment" it returns to "PlacesFragment".
This is possible, you need to call addToBackStack(null) in the fragment transactions.
Reference: Providing Proper Back Navigation
When you create your FragmentTransaction that will add/remove/replace (or whatever pattern you are using) the Fragments, just make sure to call addToBackStack(). Then, when the user presses the back button, the system will automatically cycle back through the entries added to the back stack, in reverse order from how they were originally added. No additional work is required on your part! :)
I am a new Android developer.
In iOS, there is a class called UINavigationController by which I can push a new viewController to stack and go back to the previous view by pushing the "back" button.
[self pushViewController: myViewController animated:YES]
As far as I know, the instance of UINavigationController has a property to hold the controllers. Therefore, all the attributes in each of the controllers are saved as well in the stack.
I am wondering if the Android can do something similar.
Now I have two fragments to simulate the split view as iOS.
I subclass ListFragment to represent the `lsit view* in the left side and the other fragment to represent the item detail in the right side.
When user taps one of the items in the list view it will go to another list.
SecondFragment newFragment = new SecondFragment();
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
transaction
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
getActionBar().setTitle("new items");
transaction.commit();
getActionBar().setDisplayHomeAsUpEnabled(true);
invalidateOptionsMenu();
However, I want to go back to the previous view by clicking the back button.
I realize that I should add the code as follow:
transaction.addToBackStack(null);
However, my application exits after I tap the back button.
If I want to go back, I have to make another Fragment transaction. The problem is, I want to save the content as item list in the ListFragment other than saving it to the MainActivity. It is much easier for me to retrieve the previous list view content from stack.
Is there any way in Android can do something similar in iOS as UINavigationController?
Hi I am not sure I am doing the right thing. I have several fragments in one activity (not shown at the same time). When I add the fragment do I have to check if a previous instance exists? I am using the compatibility package and my fragment CameraFragment is a separate class (in its own file):
private void addNewFragment(Fragment fragment, String tag) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.frag1, fragment, tag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
and then :
public void startPicTaking() {
addNewFragment(CameraFragment.newInstance(), TAG_PIC_TAKING);
}
So each time a user clicks a button to take a picture I use this methods BUT shall I verify if the fragment already exists and remove it first or does the static method newInstance make sure the fragment is not duplicated?
I have read the doc several times but I don't understand why the line:
ft.addToBackStack(null);
what is it for? I know you can pop the back stack and it keeps the transaction but how can it be used and for what? Is it necessary or if I don't use it I can skip it?
thanks
I have several fragments in one activity (not shown at the same time). When I add the fragment do I have to check if a previous instance exists?
No, it will just create a new instance of that Fragment when it adds the next instance of it. It will not affect the previous instance of it.
So each time a user clicks a button to take a picture I use this methods BUT shall I verify if the fragment already exists and remove it first or does the static method newInstance make sure the fragment is not duplicated?
You could do that if you wanted to, to ensure that no Fragment appears twice in the stack. (So when you hit back, you don't get the same activity again.) Depending on exactly what appears in your back stack, you may not want to remove stuff lower down. (Consider that a user expects previous fragments to appear when he hits the back button.)
I have read the doc several times but I don't understand why the line: ft.addToBackStack(null); what is it for?
When Fragment objects are added to the back stack, then each time the user hits back, they will go to the previous item on the stack. If you do not add an item to the back stack, the user will not encounter it when they hit the back button.
Assume I have an Activity which contains two FrameLayouts (let's call them FrameA and FrameB) which in turn each contain a Fragment (let's call them FragmentA1 and FragmentB1 respectively). Now, I commit a series of individual fragment transactions using code similar to the following...
getFragmentManager()
.beginTransaction()
.replace(frameId, fragment)
.addToBackStack(null)
.commit();
... such that I replace FragmentA1 in FrameA with FragmentA2, then I replace FragmentB1 in FrameB with FragmentB2, then I replace FragmentA2 in FrameA with FragmentA3, then I replace FragmentB2 in Frame2 with FragmentB3, and the final state looks like the picture above (where only FragmentA3 and FragmentB3 are visible).
If I understood correctly how the back stack works, pressing 'back' will interleave popping of the Fragments between FrameA and FrameB (reflecting how I added them).
Does anyone know if it is possible to pop the last transaction on FrameA or FrameB selectively? (i.e. if I pressed 'Pop FrameA' then FrameA would be transitioned back from FragmentA3 to FragmentA2 and, instead, if I pressed 'Pop FrameB' then FrameB would be transitioned back from FragmentB3 to FragmentB2)
Supplement: I know I can get the Fragment last added to a given FrameLayout using the FragmentManager.findFragmentById(int framelayoutId) method, but calling FragmentTransaction.remove(fragment).commit() only removes the Fragment from the View and does not transition the View back to the Fragment it previously displayed.
Basically, no, there is only one back stack for an activity.
You will just need to implement your own separate back stacks.
As of Android 4.0 (and the associated support library) there are APIs that should make this relatively easy -- FragmentTransaction.detach(Fragment) lets you put a fragment into the same state it is when in the back stack, and FragmentManager.saveFragmentInstanceState(Fragment) lets you go further and completely throw away the Fragment object. Not coincidentally, these are used to implement ViewPager's FragmentPagerAdapter and FragmentStatePagerAdapter, respectively, so you could look at the code for these as an example of how to use them.
FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)
Here is the simplest answer, and the explanation is very clear: Well there are a few ways to go about this depending on the intended behavior, but this link should give you all the best solutions and not surprisingly is from Dianne Hackborn...