I have this problem in an app, where that method below doesn't always effectively hide the currently visible fragment (contentFragment) and shows the new one (fragment). Basically, sometimes, it does the complete opposite of what it's supposed to do, that is, the current fragment remaining visible, and the new one not showing at all. And what is worth, is that I can't always replicate when it happens.
I'm really at wits' end here. Anyone got any ideas?
public void addContentFragment(GenericFragment fragment) {
FragmentManager fragmentManager = slidingMenusActivity.getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.ContentLayout, fragment, fragment.getFragmentTag());
transaction.addToBackStack(fragment.getFragmentTag());
Log.d(TAG, "addContentFragment hiding contentFragment=" + contentFragment);
transaction.hide(contentFragment);
transaction.commit();
fragmentManager.executePendingTransactions();
contentFragment = fragment;
}
Your contentFragment sometimes do not have the value you are expecting, try to retrieve the current fragment to ensure you are really hiding the fragment before your new transaction.
Modify your addContentFragment(GenericFragment fragment) as the follows:
public void addContentFragment(GenericFragment fragment) {
FragmentManager fragmentManager = slidingMenusActivity.getSupportFragmentManager();
Fragment currentFragment = fragmentManager.findFragmentById(R.id.ContentLayout);
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.ContentLayout, fragment, fragment.getFragmentTag());
transaction.addToBackStack(fragment.getFragmentTag());
Log.d(TAG, "addContentFragment hiding contentFragment=" + contentFragment);
transaction.hide(currentFragment);
transaction.commit();
}
Related
Here's my Flow/Structure:
Activity
Fragment
Same Fragment within it.
I have overriden removeCurrentFragment() method which does go back functionality by removing Fragment by ID as follows -
#Override
public void removeCurrentFragment() {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment currentFrag = getSupportFragmentManager().findFragmentById(R.id.fragment);
if (currentFrag != null)
transaction.remove(currentFrag);
transaction.commit();
}
It seems, when this happens, as ID of both fragment is same, it creates blank view.
If more details are required, please feel free to ask in comments. I will edit question as per required details.
I thought it was related to remove fragment, But I made new fragment with separate XML, still I am having the same issue.
I have parent fragment with pagination (as I need horizontal page scroll) in it have the child fragment, when clicking on child fragment button new fragment is replaced so when it is removed the X and Y of the child fragment is also disturbed.
here is the before and after screenshot of the x and y axis of child fragment.
Before
After
can any one suggest what could be the issue?
You have to use a tag to load the Fragment, and then use that same tag again to remove it.
For example, to add the Fragment:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
fragmentManager.popBackStack(tag, androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE);
ft.setCustomAnimations(R.anim.enter, R.anim.exit);
ft.add(containerId, fragment, tag);
ft.addToBackStack(tag);
ft.commit();
To remove it, again use the same tag:
if (fragmentManager.findFragmentByTag(currentTag) != null) {
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.remove(fragmentManager.findFragmentByTag(currentTag));
ft.commit();
}
So, I have this problem: I am initializing a fragment - AddingTaskFragment
here's code:
Initializing AddingTaskFragment
private void initFragment()
{
// Get fragment manager
FragmentManager fm = getSupportFragmentManager();
// Begin transaction
FragmentTransaction ft = fm.beginTransaction();
// Create the Fragment and add
addingTaskFragment = new AddingTaskFragment();
ft.add(R.id.fragment_task_type_container, addingTaskFragment, "addTaskFragment");
// ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
// Commit the changes
ft.commit();
}
And it works fine
But then, I call some event, that replaces this fragment with other one(AddingScheduleFragment).
Replacing fragment
#Override
public void onScheduleTypePick()
{
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
// Create the fragment and attach book index
addingScheduleFragment = new AddingScheduleFragment();
// Replace the book list with the description
ft.replace(R.id.fragment_task_type_container, addingScheduleFragment, "addScheduleFragment");
ft.addToBackStack(null);
ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
ft.commit();
}
And when I'm poping my previous fragment(AddingTaskFragment) from the stack. All of my EditViews are gaining focus.
Returning previous fragment
#Override
public void onTaskTypePick()
{
getSupportFragmentManager().popBackStack();
}
What can be wrong? Why is this happening? Thanks for answers.
Important: When I replacing AddingTaskFragent with new object everything works great.
So, I've solved the problem by myself. Rather found the similar one.
afterTextChanged() callback being called without the text being actually changed
When the fragment was attached second time(because of .replace() method) it was restoring the previous state of the views. And then all textChangeListeners triggered.
I have a fragment in which there is a nested fragment which I add in this way:
if (home == null) {
home = new MyFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(MyFragment.class.getName());
transaction.add(R.id.child_fragment, home).commit();
}
When I enter another fragment and go back the child fragment from above is not there. I checked and the instance is different from null.
UPDATE: I changed the code as suggested by Ashwin S Ashok but it's still not working.
Try using these methods:
// Use this if you don't want to retain the fragment.
protected void replaceFragmentStack(int container, Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(container, fragment);
fragmentTransaction.commit();
}
// Use this if you want to add the fragments in a stack.
protected void addFragmentStack(int container, Fragment fragment, String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.add(container, fragment, tag);
fragmentTransaction.addToBackStack(tag);
fragmentTransaction.commit();
}
I would suggest you to use getChildFragmentManager() when making transactions inside a fragment. And its a bug i guess.
You can check out this thread it will help you alot Android 4.2: back stack behaviour with nested fragments
Also you need to go through The Curious Techizen's blog
Here is the link for the github project sample for same mechanism
I hope this will help you.
I have Fragment XYZFragment where i display the list view.On the Listview item click i replace the Fragment like this.
Fragment fragment=new XYZFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft= fragmentManager.beginTransaction();
ft.addToBackStack(null);
ft.replace(R.id.content_frame, fragment).commit();
But my problem is when i click back button the fragment reload the listview.It is never happen when i used to use Activity.
So my question is how to save the instance of previous fragment so that it will prevent the reloading of Data.
without seeing your code we can't help you out but from your question i can figure out the problem, this solution may help you out.
create stack such that
private static Stack<Fragment> myFragStack;
myFragStack = new Stack<Fragment>();
//To Load the fragment
public void loadFragment(Fragment fragment){
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
myFragStack.lastElement().onPause();
ft.hide(myFragStack.lastElement());
myFragStack.push(fragment);
}
//onBackPressed
public void onBackPressed() {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
if (myFragStack.size() > 1) {
ft.remove(myFragStack.pop());
myFragStack.lastElement().onResume();
ft.show(myFragStack.lastElement());
ft.commit();
}
}
It's a sample code.. you can change it as per your requirement.
ft.replace() will completely remove the view & will lose the context so you can't maintain your list state, but using stacks maintaining fragments with hide-show will solve your problem.
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();