I um uzing this code:
FragmentManager FManager = getFragmentManager();
FragmentTransaction FTransaction = FManager.beginTransaction();
FTransaction.setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragment.setArguments(fragment.getArguments());
FTransaction.add(ResourceId, fragment, label);
FTransaction.addToBackStack(backStack);
FTransaction.commit();
and I m geting this on my activity:
http://i.stack.imgur.com/K9NKy.png
can someone help me?
I hope that my simple answer will help you. Currently, You are loading an another fragment over your main fragment. you need to "hide" or "remove" or "replace" with old one. As i mentioned them below
In case of Remove or Hide
Fragment fr2 = fragmentManger.findFragmentByTag(Constants.TAG_Detail_Page);
if (fr2 != null)
fragmentTransaction.remove(fr2);
While for "Replace", you will assign new fragment to contentView:
FTransaction .replace(R.id.fragment_container, newFragment);
You are asking the fragment manager to add another fragment and it is doing just that. You never tell it to do anything to the original fragment. If you want to remove the exisitng fragment and show a new one then you should be calling:
FTransaction.replace(...)
instead of calling add.
If the original fragment has been added via the xml layout file, it is more difficult to replace. There are multiple SO questions dealing with that situation.
Related
I've done some research but I really couldn't find the answer.
I have single activity with side menu, and holder. I have many (non support) fragments, and all of them are using same holder (one at a time).
When user uses menu (it's in main activity), and goes another page, I want to add name of the current fragment to backstack (using .addToBackStack(Fragment1.class.getName())), but I couldn't find how to get current fragment.
I don't want to implement interface etc to keep track of current fragment. There is a super simple way using fragmentManger isn't there?
You can get your current fragment like this:
if (getFragmentManager().getBackStackEntryCount() > 1) {
Fragment f = getFragmentManager().findFragmentById(R.id.content_frame);
if (f instanceof BlankFragment) {
// Do something
}
}
OK,
If you want to get latest entry from backstack(thanks to #AndroidGeek);
fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-1);
and, if you want to get currently active fragment (thanks to #Salman500 #AndroidGeek);
Fragment f = getFragmentManager().findFragmentById(R.id.fragment_holder);
you can use this to get fragment id for non support fragment
Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_id);
if(fragment!=null)
{
getFragmentManager()
.beginTransaction()
.addToBackStack(null)
.commit();
}
You can keep track of fragments in the main activity (with variables) and access them there. Example:
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction= manager.beginTransaction();
MyFragment myFragment = new MyFragment();
myFragment.doSomething();
Adding to the back-stack:
FragmentTransaction fragment = getSupportFragmentManager().beginTransaction();
fragment.addToBackStack(fragment);
fragment.commit();
This is answered here: get currently displayed fragment
Just use addToBackStack() before you commit() the fragment trancsaction. See it here
So your code will look like :
...
fragmentTransaction.replace(R.id.holder, newFragmentToShow, newFragmentTag);
fragmentTransaction.addToBackStack();
fragmentTransaction.commit();
...
EDIT : after OP was edited
You do not need the fragment class to call addToBackStack() as you have mentioned in the OP. The String argument is an optional string just to keep the state for the backstack state. You should see the documentation
It is all internally managed and the current active fragment is automatically added to the backStack, you may call it from where ever you want, it will always use current active fragment.
Working with fragments I've always used replace() for my transactions, but I wish I didn't have to save instance states anymore to restore a fragment's view and prevent reloading when coming back to that fragment. So, I've decided to work with add(). The thing is when I add another fragment, the previous fragment view remains in the background and that's fine (that's the behavior I expected), but the problem is I can actually interact with the views in the background. Example:
Fragment A has a Button
Fragment B has a TextView
When I add Fragment A and later add Fragment B, I'm able to click on Fragment A's Button, even staying on Fragment B's view.
I'm using:
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction().
add(getRootViewContainer(),fragment,fragment.getClass().getSimpleName());
if (shouldGoBack)
fragmentTransaction.addToBackStack(fragment.getClass().getSimpleName());
where getRootViewContainer() returns the id of the FrameLayout I'm using as my activity main container.
Now, is it really the default behavior of add()?
If so, is there a proper way to avoid this or one just has to use replace()?
What you can do here is just hide previous fragment at the time of transaction of current fragment.
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment newFragment= new MyFragment ();
ft.hide(CurrentFragment.this);
ft.show(newFragment);
ft.commit();
It worked for me just try it.
FragmentTransaction.hide(fragmentBehind); //works for me!
example :
//I have it globally available
FragmentTransaction trans = MainActivity.getManager().beginTransaction();
//not globally
FragmentTransaction trans = getFragmentManager().beginTransaction();
MapFragment newFragment = new newFragment();
trans.add(R.id.fragmentContainer, newFragment, tag);
trans.hide(this);
trans.addToBackStack(tag);
trans.commit();
Yes, this is a default behaviour of add().
If you really don't want to user replace(), you can try to disable views which are inside "old" fragment.
I am develop the app using the fragments and i am facing one fragment1 adding to the another fragment2
fragment1 onclicks performing fragment2 .I didn't findout the solution for that. please guide anyone know
I am using the following code to add the fragment
Fragment2 fragment2=new Fragment2();
FragmentManager fragmentManager = activity.getFragmentManager();
android.app.FragmentTransaction ft=fragmentManager.beginTransaction();
ft.add(R.id.container,fragment2);
ft.hide(new Fragment1());
ft.addToBackStack(Fragment1.class.getName());
ft.commit();
The above to use adding onefragment1 adding to fragment2.Fragment1 onclicks perform to fragment2 . i didn't findout mistake.
please guide me anyone know .Advance thanks to all
nested Fragments are not recommended and for adding a fragment to a container from another Fragment use the parent Activity to do so , you can define a function inside Parent Activity which replace current Fragment with your second Fragment and call it from your first.
Adding a fragment to another fragment is the concept of nested fragments and not recommended. You should replace the fragment instead of adding. Use the following:
Fragment fragment = new Fragment2();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().addToBackStack("fragment").replace(R.id.frame_container, fragment).commit();
I've setup a new Android project that comes with an activity. Here's the boiler plate code:
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
Can someone explain what this is doing exactly? From what I can see, it checks if the activity hasn't been initliazed and then inflates the layout. But what I don't understand is beginTransaction(), ew PlaceholderFragment(), and commit()
Thanks.
You use fragment transactions to add / replace (etc) fragments within a FrameLayout (R.id.container) and new PlaceholderFragment is a new instance of a fragment to be put into the container
//Check whether we're recreating a previously destroyed instance
if (savedInstanceState == null) {
//Execute a transaction, replacing any existing fragment with this one inside the frame.
//Getting FragmentManager object which will control fragment acvitiy
FragmentManager fm = getFragmentManager()
//Starting a FragmentTransaction which will handle transaction to this fragment activity
FragmentTransaction ft = fragmentManager.beginTransaction();
//Add a fragment to the activity state. This fragment may optionally also have its view (if Fragment.onCreateView returns non-null) into a container view of the activity.
ft.add(R.id.container, new PlaceholderFragment());
//Schedules a commit of this transaction.
ft.commit();
}
There is a good explanation to fragment activity here, here and here
FragmentManager is a class which helps in managing the fragments that an activity may need. So here you are basically getting an instance of it and you are beginning a transaction. You need an instance of transaction because it lets the runtime know that some change is going to happen when this is called. Here 'add()' is that change and finally you commit it to save that change.
The arguments to add are the layout where the fragment needs to be added and the PlaceHolderFragment() is the name of the Fragment you need to put in.
As fragments are the way to go, replacing all of many heavy Activites, Eclipse has also adapted to this change which cause the boiler alert. :)
Starting a fragment (which cant be done via Intents) is treated as a transaction just like in database (not a good example i guess).
getFragmentManager() - gets the Activities FragmentManger which is responsible to initiate FragmentTransaction.
beginTransaction() - creates a new Transaction for this particular fragment job.
new PlaceholderFragment() - is an instance of the PlaceholderFragment which you can find if scroll more in the Activity.
commit - a way to commit this trasaction and bring it to effect.
See Android docs. for more details. :)
It is simple my friend.
In simple Coding Language:
if (savedInstanceState == null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.tab5, new PlaceholderFragment());
fragmentTransaction.commit();
}
If you think that it explain everything, then it is a pleasure for me. Otherwise just ping me to add theory information.
I have an activity with a FrameLayout in it.
The activity should show four steps, and each step is a Fragment. When I want to go back-further, I don't want my fragments to be recreated. I would like to retain them and simply replace their view in my fragment.
I used to first create my Fragments and add them in the backstack like this:
Fragment step= new Frag1ActCompleteFragsCommTrack();
FragmentTransaction ft= getSupportFragmentManager().beginTransaction();
ft.add(step, ""+onStepNr);
ft.addToBackStack(null);
ft.commit();
notice that I don't show it, I simply create it and add to the backstack.
So, once I need one of my fragments to show, I add it (in this example I don't remove any fragment from the framelayout just because it's my first add):
FragmentTransaction ft= getSupportFragmentManager().beginTransaction();
ft.add(R.id.my_frameLayout, step);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
So: the problem is that I obtain a
Caused by: java.lang.IllegalStateException: Fragment already added: Frag1ActCompleteFragsCommTrack{410dcb20 #0 id=0x7f050041 -1}
But I think I can't add directly into my framelayout the first time, otherwise the next time I replace it, I could lose my fragment. Am I right? So.. what's the best practice for retaining fragments that could interchange each other in a framelayout?
Ladies and gentlemen, I did it!
If you add a Fragment, and you want it to be shown in a framelayout, remember to put it in the Fragment backstack. That's it! If you replace it in the framelayout with another one, no worries: you can put it back by finding it thanks to its tag.
It was easier than I thought actually
//step is an int describing the step associated to the fragment I wanna place
FragmentTransaction ft= getSupportFragmentManager().beginTransaction();
ft.replace(R.id.act_complete_track_frameLayout, f, ""+step);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
if(firstAttach)
ft.addToBackStack(null);
ft.commit();
imagine a fragment with tag "1" replaced through the code above by a fragment with tag "2". If I want to go back to step1, I reuse that code by obtaining my old fragment with getSupportFragmentManager().findFragmentByTag("1")
To be short, I thought that FragmentTransaction.replace removed the fragment from the backstack as well. That seems not to be the case (luckily)
You can always do something like fragmentManager.putFragment(yourFragment);
If I understand correctly, you are trying to add all the fragments but not show them until you are ready. FragmentTransaction.add() doesn't exactly do that though. It will also be shown after its added. You should use hide() after adding each fragment, and then later you can use show() to make it visible, and hide() again to make other fragments invisible.
Like this:
Fragment step = new Frag1ActCompleteFragsCommTrack();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(step, ""+onStepNr);
ft.hide(step);
ft.commit();
Then later:
Fragment step = getSupportFragmentManager().findFragmentByTag(""+onStepNr);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.show(step);
// may want to hide other fragments here
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();