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();
}
}
Related
I have a Activity where I load 3 fragments one after another
FragmentA
FragmentB
FragmentC
Flow is Like this I have used Adding fragment one above another
Start-Activity -----> Load FragmentA ----> Load FragmentB ----> Load FragmentC
What I am trying to do now is:
Now assuming now FragmentC is the top fragment shown
I want to find the FragmentA from the stack and just show it instead of creating a fragmentA all over again
Code I have used to add fragmentA is for Example:
Fragment fragment = null;
FragmentTransaction fragmentTransaction = null;
fragment = new FragmentA();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.addToBackStack(FragmentA.class.getSimpleName());
fragmentTransaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
fragmentTransaction.add(R.id.container, fragment, FragmentA.class.getSimpleName());
if(fragment!=null && fragmentTransaction!=null){
fragmentTransaction.commitAllowingStateLoss();
}
Look at FragmentManager.getBackStackEntryAt method, from there you can go back to any fragment of your history…
Loop through the back stack entries, meanwhile, if you find any matching Fragment by id or tag, just pop back stack inclusive with fragment A's name/tag so that the fragment A is just displayed rather than adding once again.
The example code to retrieve a fragment by Tag would look like this
FragmentA frA = getSupportFragmentManager().findFragmentByTag(FragmentA.class.getSimpleName());
and if it's not null you can reuse it in your container
if(frA != null) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
//you could add this transactionn to backstack again here if you want to be able to pop it later
fragmentTransaction.add(R.id.container, frA, FragmentA.class.getSimpleName());
} else {
//if your fragment is null as it was destroyed previously you can create a new one here
}
You are giving a tag, fragmentTransaction.addToBackStack(FragmentA.class.getSimpleName()); to the transaction , you can use the same tag to find the fragment in the backstack, before creating a new frgament, check the backstack for the fragment using findFragmentByTag on the fragment manager, if it exist, the method returns the fragment otherwise null
try it!
val fm: FragmentManager? = fragmentManager
for (entry in 0 until fm.getBackStackEntryCount()) {
Log.i(TAG, "Found fragment: " + fm.getBackStackEntryAt(entry).getId())
}
I am trying to do the following use case in Android Fragments. I have 2 fragments.
Fragment A -> Fragment B
When a user does something in Fragment B, I want to have the back stack as follows
Fragment A -> Fragment C. So, when the user presses back I want the user to go back to Fragment A.
I have tried the following
mFragmentManager.popBackStackImmediate();
FragmentTransaction fragmentTransaction = fMgr.beginTransaction()
.replace(R.id.base, Fragment_C, "1")
.addToBackStack(null)
.commitAllowingStateLoss();
The problem here is that I can see Fragment A for a short period of time before Fragment C is shown
If I do the following
mFragmentManager.popBackStackImmediate();
FragmentTransaction fragmentTransaction = fMgr.beginTransaction()
.replace(R.id.base, Fragment_C, "1")
.addToBackStack(null)
.commitNowAllowingStateLoss();
I get the error
This transaction is already being added to the back stack
I can get Fragment C to show up if I do this BUT
mFragmentManager.popBackStackImmediate();
FragmentTransaction fragmentTransaction = fMgr.beginTransaction()
.replace(R.id.base, Fragment_C, "1")
.commitNowAllowingStateLoss();
This works and I don't see Fragment A and see Fragment C but the back button takes the user out of the application. So, is it possible that we can pop the back stack of the fragment and then add another fragment to the back stack w/o showing Fragment A AND the back button takes the user back to Fragment A
Here is an easy method to add fragments to fragments or to adapters within fragments...
from your base activity, make your fragment manager static. assume this activity is called dashboard.
static FragmentManager support;
Don't forget to initialize this in onCreate.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_dashboard);
support = getSupportFragmentManager();
define your new fragment inside your adapter or fragment.
users_item_fragment dialog = new users_item_fragment();
//also, let's add some data...
Bundle args = new Bundle();
args.putString("device", devicesList.get(position));
use the following method to add the fragment easily wherever you would like
//pick an easily remembered tag
public void replace(Fragment fragment, String tag){
FragmentManager man = dashboard.support;
FragmentTransaction fragt = man.beginTransaction();
if(!fragment.isAdded()) {
dashboard.lastTag = dashboard.fragtag;//not needed, but helpful w/ backpresses
fragt.add(R.id.fragment_container, fragment, tag)
.hide(man.findFragmentByTag(fragtag)).commit();
dashboard.fragtag = dashboard.tag;//not needed, but helpful w/ backpresses
}
if(fragment.isAdded() && fragment.isHidden()) {
dashboard.lastTag = dashboard.fragtag;//not needed, but helpful w/ backpresses
fragt.show(fragment);
fragt.hide(man.findFragmentByTag(fragtag)).commit();
dashboard.fragtag = dashboard.tag;//not needed, but helpful w/ backpresses
}
}
To implement this with backpresses working correctly, add this in you onBackPress method of your main activity:
#Override
public void onBackPressed() {
FragmentManager man = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = man.beginTransaction();
fragmentTransaction.hide(getSupportFragmentManager().findFragmentByTag(fragtag))
.show(getSupportFragmentManager().findFragmentByTag(lastTag)).commit();
fragtag = lastTag;// holds the last fragment
}
}
It's easy to see the logic here and easy to manipulate back press events using this.
I am struggling to remove a single fragment that I add dynamically when I have multiple fragments.
For examples:
MainActivty
Inflate FragA
Inflate FragB
Inflate FragC
Now how do I just delete fragment A?
Using popBackStack kills all three and getSupportFragmentManager().beginTransaction().remove(TAG).commit(); also seems to do thae same thing
How are you meant to do this correctly? I am trying to keep multiple backstacks persistent over tabs
try this...
get current fragment title & check fragment A or not.
get current fragment title to use getTitle() Method and check
if(getTitle().toString.equals(fragment A){
// do
}else{
// do
}
Can you try this..
For eg. using fragment name as tag:
FragmentA fragment = new FragmentA();
String backStateName = fragment.getClass().getName();
Adding to backstack:
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();
Popping:
getSupportFragmentManager().popBackStackImmediate (backStateName, 0);
This should only pop the fragment with the specific tag.
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 passed data from FragmentActivity to multiple fragments like this
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("userid", logindata);
firstfragment.setArguments(bundle);
From fragment Activity to secong fragment i have pass data like this.
secondfragment.setArguments(bundle);
when i click first fragment it's working next click second fragment it's also working fine but again click first fragment the illegal state exception Fragment already active exception will be occur. How to reslove this problem please help me. Thanks in advance.
illegal state exception Fragment already active
setArguments only called before the fragment has been attached to its activity otherwise through Fragment already active Exception. so call setArguments to should need to remove fragment is already present and use replace to add fragment again.
Remove fragment before adding new :
Fragment fragment =
getSupportFragmentManager().findFragmentByTag("firstfragment");
if(fragment != null)
getSupportFragmentManager().beginTransaction()
.remove(fragment).commit();
Now add new fragment :
firstfragment.setArguments(bundle);
transactn = mngr.beginTransaction();
transactn.replace(R.id.content_frag,firstfragment).
addToBackStack("firstfragment").commit();
Try this:
createFragment(new YourFragment());
private void createFragment(Fragment fragment) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.container_app, fragment).commit();
}