Start Fragment via function in MainActivity - android

I'm trying to start a fragment programmatically. The function below works fine on its own. The problem here is, that I have to call the function from within another fragment. The call from the fragment to MainActivity works and is not the problem.
public void gotoFragment1(){
Fragment1 fragment = new Fragment1();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.nav_host_fragment, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
If I try to call the function from another fragment the app crashes with the following stacktrace:
java.lang.IllegalStateException: FragmentManager has not been attached to a host.
at androidx.fragment.app.FragmentManager.enqueueAction(FragmentManager.java:1727)
at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:321)
at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:286)
at com.fewo.info.MainActivity.gotoVeranstaltungen(MainActivity.java:134)
at com.fewo.info.ui.home.HomeFragment$1.onClick(HomeFragment.java:53)
How can I change the fragment with this code beeing called from within another fragment?

if you want replace a fragment in MainActivity from other Fragments, you can do it in your fragment (No need to call function from MainActivity),
use this in your fragment:
getFragmentManager().beginTransaction()
.replace(R.id.nav_host_fragment, new Fragment1(), FragmentLoanList.class.getName()).addToBackStack(null)
.commit();

Fragment A:
((ActivityOne) getActivity()).callFragmentB();
Activity One
public void callFragmentB(){
//run your fragment transaction To B here
}

Related

Android Back to previous fragment by popBackStack

I have 3 fragments: Home, A and B. Home and A are in mobile navigation menu.
User goes from A to B and then press back button. The issue that if I use getFragmentManager().popBackStack(); onCreateView of fragment A is calling and I have duplicating of content.
But if I use getActivity().onBackPressed(); it goes to Home fragment instead of A.
How to display fragment A by clicking back button without refreshing the view?
Here is how I make transaction from A to B
CertificateItemFragment certificateItemFragment = new CertificateItemFragment(item);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.nav_host_fragment, certificateItemFragment).addToBackStack(null);
fragmentTransaction.commit();
You need to know some premise before using FragmentManager.
in Activity there is FragmentManager and we should call it with getSupportFragmentManager(), getFragmentManager() is deprecated.
in Fragment there are multiple FragmentManagers called ParentFragmentManager and ChildFragmentManager, the final FragmentManager which is deprecated too. And ParentFragmentManager will be same as Activity's FragmentManager
getActivity().onBackPressed() will pull out fragment if any stack exists in Activity's FragmentManager
fragmentManager.popBackStack() will pull out fragment if any stack exists in Activity's or Fragment's FragmentManager rely on who calls
Base on above points
(1) If You want to hold fragments in Activity, you should call getSupportFragmentManager() in Activity, and call getParentManager() in Fragment, then onBackPressed() will pull out the fragment you last add to stack.
(2) If you want to hold fragments in a Fragment and Separated from Activity, you should call getChildFragmentManager() in Fragment, then activity.onBackPressed() will pull out the fragment which in Activity's fragment stack and ignore other fragments in Fragment's fragment stack.
For question will be same as case (1), and if you dont want re-create fragment, you should use add() instead of replace()
in Fragment A
CertificateItemFragment certificateItemFragment = new CertificateItemFragment(item);
FragmentManager fragmentManager = getParentFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.nav_host_fragment, certificateItemFragment).addToBackStack(CertificateItemFragment.TAG);
fragmentTransaction.commit();
now onBackPressed() will backstack from CertificateItemFragment to Pre-Fragment
In normal case navigation item list menu open fragment which are replace to each other but when we move inside of any item as like in your case move from fragment A to B,
In this case normally we use another activity on which create fragment.
If you do't want to use activity then, you just need to add fragment.
try below code that may help you
CertificateItemFragment certificateItemFragment = new CertificateItemFragment(item);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.nav_host_fragment, certificateItemFragment).addToBackStack(CertificateItemFragment.TAG);
fragmentTransaction.commit();

how to launch multiple fragments from a parent fragment?

i have a parent fragment and when i click in a button to open first fragment then click in button in first fragment to open a second fragment and from second fragment to third fragment and so on ....
i succeeded to do that but the application becomes very slow after launching multiple fragments
this is the code i used to launch any fragment
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
Fragment newFragment = new newFragment();
FragmentTransaction transaction =
getFragmentManager().beginTransaction();
transaction.replace(fragmentContainer.getId(), newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
});
When you are calling android.support.v4.app.FragmentManager then you must use getSupportFragmentManager().
public FragmentManager getSupportFragmentManager ()
Return the FragmentManager for interacting with fragments associated
with this activity.
If your new fragments are not transparent, I think you should check the overdraw of layouts.
The replace() needs to recreate the instance and reload data, maybe add() and hide() can help you.
i should use getActivity().getSupportFragmentManager() instead of getFragmentManager()

Fragments inside ViewPager are not destroyed

In my MainActivity in onCreate method I add() MainFragment to FrameLayout main_view_container:
if (savedInstanceState == null) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.main_view_container, new MainFragment(), MainFragment.FRAGMENT_TAG);
fragmentTransaction.commit();
}
In my MainFragment I have ViewPager with FragmentStatePagerAdapter and every page is Fragment itself (PagerFragment).
Then at some point after button click I want to replace whole MainFragment with another Fragment (ReplacementFragment) and add transaction to back stack so I can go back to MainFragment on back button pressed. So I do the following:
FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.main_view_container, new ReplacementFragment(), null);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
After I commit transaction MainFragment is stopped and onDestroyView() is called but completely nothing happens with PagerFragments (that are in ViewPager in MainFragment) Not event a single onStop() call. Then when I go back MainFragment's View is recreated in onCreateView() which means new Instance of ViewPager as well, but still nothing with PagerFragments.
How is that possible that in parent Fragment onDestroyView is called but not in children Fragments?
You must use getChildFragmentManager() when creating pager adapter inside MainFragment.

Run function in another fragment

I want to run a function from main activity, but function is another fragment. This is my code
FragmentManager fm = getSupportFragmentManager();
ConversationFragment fragment = (ConversationFragment)fm.findFragmentById(R.id.container);
fragment.addMessageToList("ok");
I placed this code to onCreate in MainActivity, and this is the addMessageToList function in fragment:
public void addMessageToList(String message) {
Log.w("Step 2",message);
}
But my app is crashing. Here logcat:
How can I fix it ?
You were using findFragmentById() when you had no fragment with that id on your Activity layout. When replacing a fragment in your container, add a tag to it. Like this:
fragmentTransaction.replace(R.id.container, frgObj,"ConversationFragment");
Then, use findFragmentByTag("ConversationFragment") to have your Fragment and execute methods with it.

Removing a Fragment from the back stack

I have a 3 fragments in an activity when the a tablet is held in portrait. However I only have 2 of these fragments when in landscape. The problem I am having is when going from portrait to landscape the activity is creating the 3rd fragment. I receive and error as this fragment cannot be created.
I have worked out that this fragment is being created because it is in the back stack.
I have tried to remove the fragment in the onDestroy method by using
FragmentTransaction f = fragmentManager.beginTransaction();
f.remove(mf);
f.commit();
However the I get an error saying that I cannot use this function after the onSaveInstanceState
What would be the correct way of taking this fragment out of the back stack?
Update
I should probably add that the fragment I am having problems with is a mapFragment from this libary
https://github.com/petedoyle/android-support-v4-googlemaps
The way I use it is like so
mf = MapFragment.newInstance(1, true);
ft = fragmentManager.beginTransaction();
ft.replace(R.id.mapContainer, mf);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack("map");
ft.commit();
You add to the back state from the FragmentTransaction and remove from the backstack using FragmentManager pop methods:
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove(myFrag);
trans.commit();
manager.popBackStack();
I created a code to jump to the desired back stack index, it worked fine to my purpose.
ie. I have Fragment1, Fragment2 and Fragment3, I want to jump from Fragment3 to Fragment1
I created a method called onBackPressed in Fragment3 that jumps to Fragment1
Fragment3:
public void onBackPressed() {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-2).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
In the activity, I need to know if my current fragment is the Fragment3, so I call the onBackPressed of my fragment instead calling super
FragmentActivity:
#Override
public void onBackPressed() {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.my_fragment_container);
if (f instanceof Fragment3)
{
((Fragment3)f).onBackPressed();
} else {
super.onBackPressed();
}
}
you show fragment in a container (with id= fragmentcontainer) so you remove fragment with:
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragmentContainer);
fragmentTransaction.remove(fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
In case you ended up here trying to figure out how to remove fragment(s) from backstack and you are using Android Jetpack Navigation component you could just use app:popUpTo and app:popUpToInclusive in action node of navigation graph xml to specify fragments that you want to pop out of back stack.
https://developer.android.com/guide/navigation/navigation-navigate#pop
Check this too
https://stackoverflow.com/a/51974492/4594986
What happens if the fragment that you want to remove is not on top of the stack?
Then you can use theses functions
popBackStack(int arg0, int arg1);
popBackStack(String arg0, int arg1);

Categories

Resources