I am writing an android app using ActionBarSherlock
My layout file is:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/fragment_menu"
android:layout_width="#dimen/menu_size"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="#+id/dummy"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Depending the category is selected in Menu fragment, I replace the fragment in dummy FrameLayout.Eg:
Bundle extras = new Bundle();
extras.putInt(ProgramDetailFrament.EXTRA_PROGRAM_ID, programId);
final ProgramDetailFrament fragment = ProgramDetailFrament.newInstance(extras);
getSupportFragmentManager().beginTransaction()
.replace(R.id.dummy, fragment)
.addToBackStack(null)
.commit();
getSupportFragmentManager().executePendingTransactions();
But the replaced fragment still receives touch/click event when I interact with the visible fragment. I don't know whether SherlockFragment is related to this issue?
I solved that by setting click event on the root layout of the visible fragment and do nothing in this event. But It seems a ugly solution.
Anyone knows how to solve it.
Thanks in advance.
As you state in your question, you're trying to replace a Fragment with another, so you should use the replace method of FragmentTransaction.
Here's roughly how to do it :
Bundle extras = new Bundle();
extras.putInt(ProgramDetailFrament.EXTRA_PROGRAM_ID, programId);
ProgramDetailFrament fragment = ProgramDetailFrament.newInstance(extras);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.id_of_fragment_container, fragment, DETAIL_FRAGMENT_TAG);
ft.commit();
I hope this helps ;-)
You actually need to use the replace function instead of add. What you're doing is adding a fragment on top of the other one, so you're creating a stack of fragments which are all still visible, only you don't see them because the top fragment covers all the other ones.
Use replace instead of add:
getSupportFragmentManager().beginTransaction()
.replace(R.id.dummy, fragment)
.addToBackStack(null)
.commit();
getSupportFragmentManager().executePendingTransactions();
This will remove all the other fragments in the dummy container and add the fragment you selected.
Related
when i have two fragments that are stacked on top of each other in a framelayout using "add" transaction how can i know what the call back is when one is removed.
so imagine i have a framelayout like this:
<FrameLayout
android:id="#+id/fl_cart_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"/>
and then i add two fragments like this:
mFragment = new ExampleOneFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fl_cart_address, mFragment).commit();
mFragment = new ExampleTwoFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fl_cart_address, mFragment).commit();
now if i hit the back button then fragmentTwo is gone. but what call back can i get in FragmentOne so i know that its actually gone ? Basically i just need a callback when the top fragment gets popped off the backstack. I tried onResume but its not working.
use FragmentManager.OnBackStackChangedListener
Register a callback to using FragmentManager.addOnBackStackChangedListener(FragmentManager.OnBackStackChangedListener listener)
it will send you a callback when the Backstack is changing.
I am trying to display a nested ListFragment inside my DialogFragment.
Apparently I cannot just declare a <fragment> in the XML for my DialogFragment layout because fragments-in-fragments need the childFragmentManager. So I am trying to do this in my DialogFragment:
Fragment listfragment = new ClassThatExtendsListFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(????????, listfragment).commit();
I have absolutely no idea what resource ID I need to put in the ???????? section, or how I'd even go about assigning it.
simply add FrameLayout in you layout. suppose you gave it's id as "container",
Fragment exampleFragment = new ExampleFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.container, exampleFragment).commit();
My requirement also was same like you. below code worked for me.
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MyTripFragment myTripFragment = new MyTripFragment();
fragmentTransaction.add(R.id.fragment_container, myTripFragment);
fragmentTransaction.commit();
XML code:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Hope it will help for you.
I'm not sure what type of layout you're using for your DialogFragment, but generally in the XML that DialogFragment inflates you need to add a FrameLayout and importantly give it an ID. Then when you do your fragment transaction you pass in the resource id of that FrameLayout
XML:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
</LinearLayout>
If you want to use nested fragments you'll need to call getChildFragmentManager():
FragmentManager fragmentManager = getChildFragmentManager()
Then for your fragment transaction:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, new MyFragment()).commit();
You might want to use the add method instead of replace, but thats up to you
You might also want to add the previous fragment to the backstack if you want the enable back button presses:
fragmentTransaction.replace(R.id.fragment_container, new MyFragment()).addToBackStack(null).commit();
Say I have an activity and there are two placeholder in the view:
<RelativeLayout>
<RelativeLayout id="fg_1" ...>
<RelativeLayout id="fg_2 ...>
</RelativeLayout>
Now once something happened I will add a fragment to the view by these codes:
private void showFragment(Fragment fragment, int id) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(id, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
For example, when I trigger action 1, the Fragment1 will show, when trigger action2 Fragment2 will show.
Now when I click the back menu, in my opinion, the Fragment2 will disappear, and when I click back menu again, the Fragment1 will disappear, and the app will exit once I click back menu again.
However the app will exit even I click the back menu once, it seems that the addToBackStack does not work as I expected.
Did I miss anything?
I would like to say that you have to replace with same container.
Here you have taken 2 Relative layout as container.
<RelativeLayout>
<RelativeLayout id="fg_1" ...>
<RelativeLayout id="fg_2 ...>
</RelativeLayout>
Which should be like
<RelativeLayout>
<RelativeLayout id="fg_1" ...>
</RelativeLayout>
Replace your fragment with 1 Relative layout ( fg_1 ) container.
Let me know for the same if any issue.
Hope it will help you.
Edit:
Make sure you are using same FragmentManager, same Fragment. Means I have faced same issue before 2 months that I have used android.app.FragmentManager in one class and and android.support.v4.app.FragmentManager in other class.
May be it would be help you.
Remove the addBackStack(null) method from your code. after click on back press to exit the app.
private void showFragment(Fragment fragment, int id)
{
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(id, fragment);
fragmentTransaction.commit();
}
When click the items of NavigationDrawer,The main activity container switch the fragments to show,It worked fine until I met this:
1.Switched to FragmentA, which CONTAINS A VIEWPAGER,it showed well.
2.Switched to fragmentB,fragmentB showed well.
3.Swiched back to
FragmentA,it shows as a Blank View
I tried to flip horizontally on it,I can see the viewpager index do changed(in log),But I don't know why it showed as a blank page.
*and,if fragmentA dose not contains viewpager,it worked well
Any suggestion would be appreciated.
I use replace() to switch between the fragments:
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, currentFragment)
.commit();
Possible reason might be not using replace transaction instead you mightbe adding fragments and adding it to backstack. Try using replace transaction, and see if it works.
Fragment1 firstFragment = new Fragment1();
Bundle bundle = new Bundle();
firstFragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction()
.replace(R.id.article_fragment, firstFragment)
.commit();
Learn More on Fragments adding to back stack:
Android Fragment transaction: FragmentManager and Backstack
My project contains two fragment :
FragmentA : the fragment loaded by default when the app starts
FragmentB : replace the fragmentA when a click on a button is done.
This is the XML of my main view :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/main_fragment_container"
android:name="fragmentA"
android:layout_width="match_parent"
android:layout_height="match_parent">
</fragment>
</LinearLayout>
When I wish to replace the FragmentA by the FragmentB, I use this code :
FragmentTransaction fragmentTransaction = getSupportFragmentManager()
.beginTransaction();
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.main_fragment_container, new FragmentB());
fragmentTransaction.commit();
This code works fine. My FragmentA is replaced by the new FragmentB. But when a click is done on the back button, I wish replace the FragmentB by the FragmentA by using popBackStackImmediate().
This is the code I use:
if (getSupportFragmentManager().getBackStackEntryCount() > 0){
boolean done = getFragmentManager().popBackStackImmediate();
fragmentTransaction.commit();
}
The function popBackStackImmediate return always false and the FragmentB still in foreground.
Why the FragmentA does not replace the FragmentB when I call popBackStackImmediate ? Is anybody has an idea to solve my problem?
thanks in advance
You use the getSupportedFragmentManager() to replace FragmentA by FragmentB. But you call popBackStack() on the getFragmentManager().
If you are adding the Fragments to the android.support.v4.app.FragmentManager you also have to call popBackStack() on the same FragmentManager.
This code should solve the problem:
if (getSupportFragmentManager().getBackStackEntryCount() > 0){
boolean done = getSupportFragmentManager().popBackStackImmediate();
}
You should call
fragmentTransaction.addToBackStack(null);
after performing all operations such as add(), remove(), and replace() and Just before commit(). Only then this transaction will be added to backstack. Only then you will be able to return to previous fragment state with Back button. Details here.
The problem is you're mixing Fragment and methods from the support library.
If you are using the support library, make sure:
your Activity extends from the android.support.v4.app.FragmentActivity
your Fragment extends from android.support.v4.app.Fragment
use getSupportFragmentManager() to get the android.support.v4.app.FragmentManager
Your code in the Activity would be:
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStackImmediate();
}
Please be aware that if you would like to get the FragmentManager from the Fragment code, you have to use the getFragmentManager method, as explained in the documentation (probably that's the cause of some confusion if you don't have much experience).
If you are not using the support library:
your Activity extends from the android.app.Activity
your Fragment extends from android.app.Fragment
use getFragmentManager() to get the android.app.FragmentManager
Your code would be:
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStackImmediate();
}
fragmentTransaction.commit(); is not necessary in both cases, so remove it.
Also, please call fragmentTransaction.addToBackStack(null); just before the commit but after the other operations.
I will suggest using the fragment replacement with Tag to produce the same result .
Add the fragment B to activity with tag
fragmentTransaction.replace(R.id.main_fragment_container, new FragmentB(),"TAG_B");
Fragment A -> Fragment B [onBackPressed] -->Fragment A
Override the onBackPressed() in the Activity files where ,
// check for fragment B and you are viewing fragment B
if (getSupportFragmentManager().findFragmentByTag("TAG_B")!=null)
{
fragmentTransaction.replace(R.id.main_fragment_container, new FragmentA(),"TAG_A");
}
addToBackStack("TAG") and popBackStackImmediate("TAG") always revert to fragment condition without any data in the UI right before fragment is created or added to activity !
The problem is in the order of your code. Here are two things you need to pay attention to.
You need to use addToBackStack() after your adding,
replacing fragment. Then commmit()
Then popBackStackImmediate can reverse the operation and it is working. I hope it solves the problem. I know it is an old post but I
do encounter a similar problem and wish this update can help others. Below should be the correct order:
FragmentTransaction fragmentTransaction =getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.main_fragment_container, new FragmentB());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
If you are Struggling with addToBackStack() and popBackStack() then simply use
FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, new HomeFragment(), "Home");
ft.commit();`
In your Activity In OnBackPressed() find out fargment by tag and then do your stuff
Fragment home = getSupportFragmentManager().findFragmentByTag("Home");
if (home instanceof HomeFragment && home.isVisible()) {
// do you stuff
}
For more Information https://github.com/DattaHujare/NavigationDrawer I never use addToBackStack() for handling fragment.