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()
Related
I have an activity with a viewpager that contains 2 tabs. Each tab is a host fragment that has 2 child fragments. First fragments are recyclerviews that open up other fragments with FragmentTransactions. I am having trouble creating different backstacks for them.
So in my recyclerview adapter in onBindViewHolder i have the onclicklistener like this:
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirstFragment fragment1 = new FirstFragment();
SecondFragment fragment2 = new SecondFragment();
FragmentManager fm = ((FragmentActivity) view.getContext()).getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction
.replace(R.id.frame_container, fragment2,"Tag")
.addToBackStack(null)
.commit();
}
});
If i make the transaction like this from the recyclerview, the backstack is the same for both tabs, so if i open second fragments on tab1, then on tab2, if i go back to tab1 and press back, the second fragment on tab2 gets popped insead.
If i make a button in the FirstFragment outside of the recyclerview and make the fragment transaction from FirstFragment like this:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.frame_container, SecondFragment.newInstance(), "Tag");
ft.addToBackStack(null);
ft.commit();
}
});
then it works as intended, but i want to do it from the recyclerview.
Is there any way this can be done?
You should carry your item click listener logic into the host fragment of the tab. Then in both of your host fragments you should make required transaction by using child fragment manager. Thus, the transactions are kept in the back stack of the host fragments. Then you have to manage these different stacks which are activity's fragment stack, host1's fragment stack and host2's fragment stack. For that purpose, you have to override onBackPressed in your activity then you ask the current visible host fragment for if there is a transaction. If there is you should pop that transaction and return in onBackPressed callback.If there is no let the activity to handle event by calling super.
i use fragment As follows :
img_home.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ft = fragmentManager.beginTransaction();
ft.replace(R.id.freamlayout,fragment_home);
ft.remove(fragment_setting);
ft.commit();
}
});
img_setting.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ft = fragmentManager.beginTransaction();
ft.remove(fragment_home);
ft.replace(R.id.freamlayout,fragment_setting);
ft.addToBackStack(null);
ft.commit();
}
});
but when transition to fragment 2 , stays fragment 1
how to fix it ??
img1:
img2:
You only need to call replace() which does both:
Removes the added fragments, and adds the new one you are passing as the second argument.
See:
FragmentTransaction replace
As i can see in documentation for fragmentTransaction.replace()
Replace an existing fragment that was added to a container. This is
essentially the same as calling remove(Fragment) for all currently
added fragments that were added with the same containerViewId and then
add(int, Fragment, String) with the same arguments given here.
Check
Be sure you are using v4 fragments, because app fragments are depricated in android P.
Most easy approach
If nothing works for you, put background on parent node of both of fragment layout. so the old fragment does not appear behind this.
I have a Main Menu and created a fragment and its layout.
Now I can't seems to start fragment when user presses a button on main menu.
main menu has its own layout.
now is there anyway i could initialize it from a button?
Button bt = (Button)findViewById(R.id.button1);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainMenu.this, ExercisesFragment.class));
}
});
}
I tried it by this but it gives error saying
Fragment cannot be cast to android.app.Activity
You add fragments using fragment manager:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ExercisesFragment fragment = new ExercisesFragment();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit();
read more on fragments, start here:
http://developer.android.com/guide/components/fragments.html
FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction();
ft.add(R.id.main_fragment, your_fragment);
ft.addToBackStack("ifneeded");
ft.commit();
You are doing it wrong! Intents are not used to load a fragment.
Solution is to use fragment transactions
to dynamically load the fragment you wish to bring into focus.
Here is what you need to do:
Have a container for the fragment inside the layout of you activity
Example: Assuming the layout resource of my activity is activity_main.xml, I would have a container like so
Follow this guide to create a Fragment
Assuming you already have a fragment setup with name AbcFragment, use fragment transactions to load the fragment into the container that you just created, whenever the user clicks on the button:
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getFragmentManager()
.beginTransaction()
.replace(R.id.fragment-container, new AbcFragment)
.commit();
}
});
when fragment use addToBackStack(null) method and click a method many times in an activity, the fragment page will save to back stack everytime, when I press back key, it will restore the same page, how to add the same fragment to stack just one time?
mSettingBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
SettingFragment settingFragment = new SettingFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.replace(R.id.left_framelayout, settingFragment);
transaction.addToBackStack(null);
transaction.commit();
}
});
When adding your Fragment to the backstack you should also pass a TAG to be able to identify that Fragment:
.addToBackStack(SettingsFragment.TAG);
Prior to adding the Fragment you will be able to check if this Fragment is allready in the backstack using :
getFragmentMangager().findFragmentByTag(SettingsFragment.TAG);
This will return null if the Fragment is not allready added.
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);