I have a ViewPager to implement swipe between "holder" Fragments. And inside them I need to add multiple Fragments to their respective containers.
The problem is, Im using FragmentTransaction.add(containerID, fragment);, but since there are multiple holder Fragments in the ViewPager, all the Fragments get added on the same holder Fragment, and not in the one that is calling to add them.
Anyone has an idea on a good practice to go around this problem?
Here is the code where I add the Fragments inside the holder fragment.
arrayFragments = new ArrayList<DiaAgendaFragment>();
DiaAgendaFragment objFragment;
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
//this will be set accordingly later for each fragment
Time dataFragment = new Time();
dataFragment.setToNow();
//instantiate and set fragments
for (int i = 0; i < 5; i++) {
objFragment = DiaAgendaFragment.newInstance(5, dataFragment);
arrayFragments.add(objFragment);
//pega a View pelo nome e adiciona o fragment
transaction.add(getActivity().getResources().getIdentifier("agenda5d_activity_fragment"+i, "id", getActivity().getPackageName()), arrayFragments.get(i));
//codigo de teste
dataFragment.monthDay += 1;
}
transaction.commit();
You have to use the child FragmentManager if you want to add Fragments to another Fragment. Using the normal FragmentManager will not work as you found out yourself.
In your Fragment:
FragmentManager manager = getChildFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
...
transaction.commit();
Related
In my android activity I am using multiple fragments, I am successfully switching these fragments according to my requirement but problem is that when I am switching Fragment 1 to Fragment 2 and back from Fragment 2 to Fragment 1, Fragment 1 not showing previous data Fragment 1 start from stretch, but I want to show previous data same as I was selected.
Here is my code for go Fragment 1 (fragment_search_customerProfile) to Fragment 2 (fragment_CustomerInfo):
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.filterFram, new fragment_Search());
FrameLayout layout = (FrameLayout) rootView.findViewById(R.id.cpFrame);
layout.removeAllViewsInLayout();
transaction.remove(new fragment_search_customerProfile()).commit();
Here is my code for back Fragment 1 (fragment_search_customerProfile) fromFragment 2 (fragment_CustomerInfo):
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Log.d("fragment_Search", fromSearch + "");
transaction.replace(R.id.custIndoFram, new fragment_search_customerProfile());
FrameLayout layout = (FrameLayout) rootView.findViewById(R.id.custIndoFram);
layout.removeAllViewsInLayout();
transaction.remove(new fragment_CustomerInfo()).commit();
Can anyone explain me how can I stay save my fragment data?
Instead of transaction.replace(R.id.filterFram, new fragment_Search());
you can use transaction.add to add fragment while having the data of first one
transaction.add(R.id.filterFram, new fragment_Search());
transaction.addToBackStack(null);
From fragment two you can use .show instead of replace to show the first fragment
and hide fragment two from the first one. transaction.show(getSupportFragmentManager().findFragmentByTag("firstFragmentTag")).commit();
You can simple keep the instances of the fragments, so in your Activity you would have fields like that.
private Fragment fragment1;
private Fragment fragment2;
And now you can use the sexy replace() option,
To add Fragment1
if (fragment1 == null) {
fragment1 = new fragment_Search();
}
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.filterFram, fragment1);
and same for Fragment2
And you can hold the state of the fragment (data it retrieves) in the Fragment itself, and in your onViewCreated() you check, if the state is not null, you update the view immediately.
class Fragment1 extends Fragment {
private State state;
public void onViewCreated(View v) {
if (state != null) {
// Update UI here
}
}
}
UPDATE
Using your own code
private Fragment fragment1; // This is a field outside of below method
if (fragment1 == null) {
fragment1 = new fragment_Search();
}
FragmentManager manager = getChildFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.filterFram, fragment1).commit();
FrameLayout layout = (FrameLayout) rootView.findViewById(R.id.cpFrame);
layout.removeAllViewsInLayout();
Going to fragment2 should be the same, and this code is used to go to Fragment1 and Fragment2, doesn't matter if you are going back or first time.
You have to add fragment instead of remove or replace
I am having FragmentDetail.java file which consist of recylerview,when touch on recylerview the same fragment FragmentDetail.java is called,Same process when i repeat 4 5 times by touching two simultaneously recyler view items. It does not show the back fragment immediately.Instead it shows the fragment of recyler view items.First Fragmet contains recylerview on which click ProductMenu calls,and on Product menu recyler view click FragmentDetail.java calls.So know what my problem is that on back press fragments are not getting replace properly.Below is my code :-
FirstFragment
list_recycler.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), list_recycler, new ClickListener() {
#Override
public void onClick(View view, int position) {
Fragment fragment = new ProductMenu();
fragmentManager = getActivity().getSupportFragmentManager();
fragmentTransaction = fragmentManager
.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_in, R.anim.slide_out, R.anim.slide_enter, R.anim.slide_exit);
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
ProductMenu.java
Also contains the same code.In spite of fragment FragmentDetail fragment = new FragmentDetail();
FragmentDetail.java
FragmentDetail fragment = new FragmentDetail();
ProductsBean productsBean = arr_related_product.get(position);
fragmentManager = getActivity().getSupportFragmentManager();
//final int newBackStackLength = fragmentManager.getBackStackEntryCount() +1;
fragmentTransaction = fragmentManager
.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_in, R.anim.slide_out, R.anim.slide_enter, R.anim.slide_exit);
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.commit();
what do you mean by
:
Same process when i repeat 4 5 times by touching two simultaneously recyler view items. --> ?
At first instance i would suggest do
fragmentTransaction.add(R.id.container_body, fragment);
instead of
fragmentTransaction.replace(R.id.container_body, fragment);
Let me know if it works ,also try to explain your problem little more with help of code
I am very new to programming an android as well. I am trying to add fragments using for loop. Lets say I would like to repeat fragment n-times.
for (int i = 0; i < length; i++)
{
FragmentTransaction fragmentTransaction = this.FragmentManager.BeginTransaction();
Fragment frag = _fragments[1];
fragmentTransaction.Add(Resource.Id.frameForAddressFragment, frag);
fragmentTransaction.AddToBackStack(null);
fragmentTransaction.Commit();
}
I think I have to declare Fragment for every loop with new name?
Am I right?
Could some one show me right approach.
First, I never use Xamarin, but can't you slightly change your code to this? I don't see the point of beginning a new transaction for each and every fragment. Same goes for committing.
FragmentTransaction fragmentTransaction = this.FragmentManager.BeginTransaction();
for (int i = 0; i < length; i++)
{
Fragment frag = _fragments[1];
fragmentTransaction.Add(Resource.Id.frameForAddressFragment, frag);
fragmentTransaction.AddToBackStack(null);
}
fragmentTransaction.Commit();
Second, I don't know if it's a mistake, but you have written Fragment frag = _fragments[1];. I assume you meant Fragment frag = _fragments[i];
Third, is there any problem with your code? As a reminder, your "Resource.Id.frameForAddressFragment" is supposed to be the ID of the container in which you want to add the fragment.
Last, what do you mean by this?
I think I have to declare Fragment for every loop with new name?
What "new name" are you talking about?
I am fetching data from server on fragment "A" call. When i replace "A" with "B", and after coming back to "A" from "B" , fragment "A" is called from everytime, so HTTPGET is made every time . How to avoid this and reuse fragment like REORDER_TO_FRONT in activity?
I am using this code to replace with new fragment
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.rl_fragment_content, newFragment,
backStackName);
transaction.addToBackStack(backStackName);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.commit();
And when i backpress ,
Fragment fragment = null;
fragment = getSupportFragmentManager().findFragmentByTag(
"some_fragment_name");
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.rl_fragment_content, fragment);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.addToBackStack("some_fragment_name");
transaction.commit();
Just prevent your fragment from re-inflating the view by using,
if (view != null) {
//this will prevent the fragment from re-inflating(when you come back from B)
ViewGroup parent = (ViewGroup) view.getParent();
parent.removeView(view);
} else {
//inflate the view and do what you done in onCreateView()
}
There are a few ways to do this, but the easiest would be to use add and hide on the fragment instead of replace. This code (untested) will show newFragment2 and add newFragment1 to the backstack. In your backstack code will show newFragment1 and add whatever you want to the backstack
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.add(R.id.rl_fragment_content, newFragment1,
backStackName1); //now you have an instance of newFragment1
transaction.add(R.id.rl_fragment_content, newFragment2,
backStackName2); //now you have an instance of newFragment2
transaction.addToBackStack(backStackName1);
transaction.show(newFragment2);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.commit();
and later
Fragment fragment = null;
fragment = getSupportFragmentManager().findFragmentByTag(
backStackName1);
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.show(fragment)
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.addToBackStack("whatever_you_want");
transaction.commit();
Note this will persist the view. If you want to persist between screen rotations you'll need to implement a Bundle in your host Activity.
How can I reset or reload a fragment container, to make it empty.
I have a master detail view and I want to reset the detail container to empty on a menu item click.This works in some cases and does not in some.
NullFragment fragment = new NullFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
fragmentTransaction.replace(R.id.item_detail_container,
fragment);
int count = fragmentManager.getBackStackEntryCount();
fragmentManager.popBackStackImmediate(count, 0);
fragmentTransaction.commit();
Usually you simply remove the fragment from it.
For example do something like
getFragmentManager().beginTransaction().remove(getFragmentManager().findFragmentById(R.id.your_container)).commit();
this will remove the fragment from the your_container holding it.
This gets the fragment currently present in your_container
getFragmentManager().findFragmentById(R.id.your_container)
and this remove the fragment
getFragmentManager().beginTransaction().remove(fragment).commit();
EDIT
Also sometimes it is useful to ensure all transactions are performed and finished, this can be done by using
getFragmentManager().executePendingTransactions();