Android Fragments Displaying On Top Of Each Other When Screen Orientation Changes - android

I had a navigation menu, which displays various modes of operation to the user. When the user selects a specific option, the activity is to load the corresponding fragment (Eg: Add Product should load the AddProduct fragment).
The loading works fine - I used FragmentManager together with FragmentTransaction to replace the current fragment with the new fragment. The problem comes in when the screen gets rotated - the current two fragments I have used, display on top of each other.
Here is the code I have set up for the NavigationDrawerListener (the part that does the loading):
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
DrawerLayout drawerLayout = (DrawerLayout) currentActivty.findViewById(R.id
.homeDrawer);
TextView heading = (TextView) currentActivty.findViewById(R.id.AppHeadingTextView);
switch (position)
{
case 0:
heading.setText("Home");
drawerLayout.closeDrawers();
UserMainScreenFragment homeScreen = new UserMainScreenFragment();
FragmentManager homeManager = currentActivty.getFragmentManager();
FragmentTransaction homeTransaction = homeManager.beginTransaction();
homeTransaction.replace(R.id.contentArea, homeScreen);
homeTransaction.commit();
break;
case 2:
heading.setText("Add a Product");
drawerLayout.closeDrawers();
AddProductFragment newProductFragment = new AddProductFragment();
FragmentManager manager = currentActivty.getFragmentManager();
FragmentTransaction replace = manager.beginTransaction();
replace.replace(R.id.contentArea, newProductFragment);
replace.commit();
break;
}
}

You need to create a separate layout for required activity according to orientation.

In your activity you need to check for savedInstanceState being null to avoid adding the same fragments again:
//when the orientation changes, the savedInstanceState bundle is not null
if(savedInstanceState!=null){
//add your fragment to the layout
}
another thing, I noticed you reference the fragment manager through currentActivty.getFragmentManager();
maybe the currentActivty.getFragmentManager(); has an old reference to the activity that gets destroyed, you should also use getSupportFragmentManager() if you're using the support library

You have to add different layout's (with same name) for both orientations, then Android will automatically inflate the suitable xml according to the orientation.
File structure will look like this,
res
- drawable
- layout // for portrait
- layout_name.xml
- layout-land // for landscape
- layout_name.xml // same name should be used
- .....
Find a sample solution here

Related

Android Dual Pane - Going From Details To List

I have followed the official documentation http://developer.android.com/guide/practices/tablets-and-handsets.html for Tablet support to create dual pane layout that works as shown below, in that in small screens (phones) it uses one Fragment inside one Activity to display a list of objects and another fragment inside another Activity.
Every other documentation I read talks about a one way flow from Master to details, now I want to go back the other way, from details to master and I am stuck.
In the details, I have added an Item that I want to display in the list and I want this to be dynamic such that I can add few items and each time I hit save I want the List to grow.
This is what I have done so far
In FragmentA(List Fragment) I have a method that (re)loads the data and call notifyDataSetChanged on the adapter.
I added a method in the call back that is called each time an item is added. And both Activity A and Activity B implements this listener
So when I add an item in FragmentB(Details Fragment) I call the listener and on Activity A which is housing the dual pane layout I try this
public void OnNewCustomerAdded() {
Fragment frag = null;
frag = getSupportFragmentManager().findFragmentByTag("CustomertListFragment");
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.detach(frag);
ft.attach(frag);
ft.commit();
}
Unfortunately that throws a NPE, and also if I call the methods directly in the Fragment to reload data, that throws an NPE. The only thing that works with some side effects is this
public void OnNewClientAdded() {
Intent intent = getIntent();
finish();
startActivity(intent);
}
So how can I safely restart a Fragment inside an Activity without restarting the other Fragment.
Wow, this is quite tricky, never expected it to be this challenging. Well this is how I solve it.
First I removed the second activity and reworked the code to show single pane in handheld devices and dual pane in tablets using just one Activity instead of two. This is not necessary but it helps when you are dealing with one set of lifecycles and listeners.
Then to actually have items added in the DetailsFragment appear immediately in the ListFragment while still having the Details Fragment open. I finished the containing Activity, restarted it and passed it an intent that tells it to start up the DetailsFragment
Remember that the ListFragment is set to start up no matter which device size. So you just need to start the DetailsFragment and since there is already a call back that does that it makes it easy so here is the code
//Callback method for when an item is added, called from the Details
//Fragment
public void OnNewCustomerAdded() {
Intent mIntent = getIntent();
mIntent.putExtra(Constants.SHOULD_START_CUSTOMER_DETAILS, true);
finish();
startActivity(mIntent);
}
Then in the onCreate of the Activity, after the ListFragment has been started, you do this
boolean shouldStartCustomerDetails = getIntent().getBooleanExtra(Constants.SHOULD_START_CLIENT_DETAILS, false);
if (shouldStartClientDetails){
OnCustomerListItemSelected(0);
}
The OnCustomertListItemSelected is the standard mCallback listener that you get if you created a Master/Details Activity in Android Studio, I just modified it to suit my app like so
/**
* Callback method from {#link OnCustomerListItemSelectedListener}
* indicating that the item with the given ID was selected.
*/
#Override
public void OnCustomerListItemSelected(long id) {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
CustomerDetailsFragment fragment = CustomerDetailsFragment.newInstance(id);
getSupportFragmentManager().beginTransaction()
.replace(R.id.customeractivity_detail_container, fragment)
.commit();
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
CustomerDetailsFragment fragment =
CustomerDetailsFragment.newInstance(getIntent().getLongExtra(Constants.ARG_ITEM_ID, 0));
getSupportFragmentManager().beginTransaction()
.add(R.id.customeractivity_list_container, fragment)
.commit();
}
}

Android: switching from two-pane (landscape) layout to single-pane (portrait) layout, how do I handle the switching of list and detail fragments

Background and Intro
My app consists of a single activity and 3 fragments. The app is viewed in two-panes only for 600dp smallest width in landscape only. In Portrait orientation it is viewed in a single pane nor matter which size.
Heres an overview of what it looks like.
SINGLE PANE MODE
TWO PANE MODE
Quick description of what this app does. In single pane mode fragmentAList is added to a container (R.id.list_container). When an item is pressed, its container is replaced with fragmentBDetail which contains a description and a button. Pressing this button goes to FragmentC. FragmentBDetail and FragmentC are added to back stack so the user can navigate back to FragmentAList.
In two pane mode, there are two containers (R.id.list_container) and (R.id.detail_container).
FragmentAList still goes inside R.id.list_container but clicking an item shows FragmentBDetail inside R.id.detail_container on the same screen.
The Problem I am having
I want to be able to go from two-pane mode to single pane when the orientation changes while maintaining the detail fragment. i.e. If the user was in two-pane mode and they clicked an item in the list to see the detail (say the Windows description) and when they switch to portrait orientation (single pane) I want the detail fragment (Windows description) to be shown in the single pane.
Likewise, if it was in single pane, and the user clicked a list item to see its detail. I want that detail fragment to be shown in second pane when the orientation changes to landscape.
At the current moment, if I am in two-pane mode and I switch orientation to single pane, I will see FragmentAList only. If I then click a list item I see FragmentAlist replaced with FragmentBDetail. If I then change orientation to two-pane mode, I will see two FragmentBDetails.
What I have tried
I am absolutely clueless on this problem and not sure what to do. All I have got at the moment is the tag of the fragment that is inside the detail_cotainer. With this tag I am able to find the fragment.
if(mIsTwoPane)
{
Fragment frag = getFragmentManager().findFragmentById(R.id.detail_container);
if(frag != null)
{
Log.d("TEST", "found something = " + frag.getTag());
}
else
{
Log.d("TEST", "nothing");
}
}
My Code
Below is what I deem the major parts of the code. Please let me know if you want to see others.
Main Activity
Here I am checking if I am in two pane mode. Also I add FragmentAList into the R.id.list_container (which will always be there)
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(findViewById(R.id.detail_container) != null)
{
mTwoPane = true;
}
if(savedInstanceState == null)
{
FragmentAList fragmentAList = new FragmentAList();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.list_container, fragmentAList, FragmentAList.class.getName());
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.commit();
}
}
FragmentAList
Here I get the value of mTwoPane from MainActivity. if its true, I set a variable to the ID of detail_container. If its false, I set to the ID of the R.id.list_container (which will always be there).
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.fragment_a, container, false);
mIsTwoPane = ((MainActivity) getActivity()).getIsTwoPane();
if(mIsTwoPane)
{
containerID = R.id.detail_container;
}
else
{
containerID = container.getId();
}
lvPlatforms = (ListView)view.findViewById(R.id.lvPlatforms);
return view;
}
This is used here within the onItemClickListener for the List View. the ContainerID variable contains the ID of the container based on the logic seen above in onCreateView. Also if its not in two pane mode I don't add to back stack only if its not two-pane (so the user can navigate back to the list view)
#Override
public void onItemClick(AdapterView<?> parent, View v, int pos, long id)
{
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(containerID, FragmentBDetail.newInstance(pos), FragmentBDetail.class.getName());
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if(!mIsTwoPane) //NOT in two pane mode
{
fragmentTransaction.addToBackStack(null);
}
fragmentTransaction.commit();
}
Thank you for reading.

Fragment Transaction load empty view but fragment is shown after rotating device

I am building a navigation drawer as designed by the google documentation however I have an issue where the fragment is not being replaced. http://developer.android.com/training/implementing-navigation/nav-drawer.html
When the app first loads, the default fragment is loaded.
Clicking on another item on the drawer list leaves an empty view
However on rotating the device, loads the fragment chosen.
public void selectNavActivty(int position){
// TODO Changing between the different screens selection
fragment = null;
switch (position) {
case 0:
fragment = OverLay.newInstance();
break;
case 1:
fragment = Dummy.newInstance();
break;
}
if(fragment != null) {
// attach added to handle viewpager fragments
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.replace(R.id.content_frame, fragment).attach(fragment)
.addToBackStack(null);
trans.commit();
getFragmentManager().executePendingTransactions();
} else {
Log.d("Drawer Activity","Error in creating Fragment");
}
}
For navigation menu fragment transactions I use the following approach, this way the fragment will be added and placed on top.
String name = "myFragment";
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_frame, fragment, name)
.commit();
Look up the attach() function. It follows a different fragment lifecycle.
Also make sure that your layout files framelayout is visible.
Modify your code as below:
if(fragment != null) {
// attach added to handle viewpager fragments
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.replace(R.id.content_frame, fragment);
trans.addToBackStack(null);
trans.commit();
} else {
Log.d("Drawer Activity","Error in creating Fragment");
}
If the solution doesn't work for you, share the xml code along with your fragment code.
After adding Fragment it will be added to activity state and its view
will be added to defined Container view. But by attaching nothing will
be displayed if fragment was not already added to UI. It just attaches
to fragment manager. However if view was already added to a container
in UI and detached after that, by attaching it will be displayed again
in its container. Finally you can use attach and detach if you want to
destroy fragment View temporarily and want to display and build its
view on future without losing its state inside activity.
https://stackoverflow.com/a/18979024/3329488
My solution is to tag all the fragment with unique tag on fragment replacement. Make sure you also assign a unique tag to the default fragment during it creation. A more efficient way is to identify the fragment before you recreate the same one.
public void selectNavActivty(int position){
// TODO Changing between the different screens selection
FragmentManager fragmentManager = getSupportFragmentManager();
fragment = fragmentManager.findFragmentById(R.id.content_frame);
String fragmentTag = null;
switch (position) {
case 0:
fragmentTag = "case0Tag"; // please change to better tag name
break;
case 1:
fragmentTag = "case1Tag"; // please change to better tag name
break;
default:
Log.d("Drawer Activity","Error in creating Fragment");
return;
}
if (fragmentTag != null && !fragment.getTag().equals(fragmentTag))
fragmentManager.beginTransaction().replace(R.id.content_fragment, fragment, tag).commit();
}
In my case after rotating a device a blank fragment was shown. I understood that in an Activity.onCreate() I always called creating a blank Fragment and after that a needed one. So I changed it's behaviour to this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
openEmptyFragment()
openAnotherFragment()
}
}
I recommend to check savedInstanceState != null before adding new fragments, as written in Why won't Fragment retain state when screen is rotated?.

Activity recreates Fragments on Orientation Change because reference is lost, how to avoid that?

I'm trying to learn Android Fragments and I have a very specific problem concerning Fragment management, because screen orientation screws up my implementation.
EDIT: Already solved my problem, see the "Update" below.
Short version:
Using static Fragments, if I change screen orientation, the reference to R.id.fragment is lost and the Activity re-creates the Fragment causing problems because another Fragment is still present on the Layout (because they're defined on the XML maybe).
Context:
I have a Master/Detail workflow using the default Eclipse template and I have a different type of Fragment for every tab on the ItemList. Ideally, what I want to do is switch between fragments, but I want to retain their current state without using the BackStack, since I want to navigate with the ItemList, and using the Back button to close the App.
I couldn't find any solutions for this specific problem and I tried with a lot of different approaches. Right now I'm using static fragments defined in the main Layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/item_detail_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ItemDetailActivity"
tools:ignore="MergeRootFrame" >
<fragment android:name="com.example.pintproject.DevicesFragment"
android:id="#+id/devices"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
/>
<fragment android:name="com.example.pintproject.ItemDetailFragment"
android:id="#+id/detail"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"
/>
</FrameLayout>
In the ItemListActivity onCreate(), I look for the Fragments in the layout, and add them if they aren't created yet, and I hold a reference to the current active Detail Fragment so I can hide it / show the fragment I switch to.
I'm using hide/show instead of replace because replace destroys the Fragment:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list);
if (findViewById(R.id.item_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-large and
// res/values-sw600dp). If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
// In two-pane mode, list items should be given the
// 'activated' state when touched.
((ItemListFragment) getSupportFragmentManager().findFragmentById(
R.id.item_list)).setActivateOnItemClick(true);
}
df = (DevicesFragment) getSupportFragmentManager().findFragmentById(R.id.devices);
if (df==null){
df = new DevicesFragment();
getSupportFragmentManager().beginTransaction().add(R.id.item_detail_container,df).commit();
getSupportFragmentManager().beginTransaction().hide(df).commit();
}
idf = (ItemDetailFragment) getSupportFragmentManager().findFragmentById(R.id.detail);
if (idf==null){
idf = new ItemDetailFragment();
getSupportFragmentManager().beginTransaction().add(R.id.item_detail_container,idf).commit();
getSupportFragmentManager().beginTransaction().hide(idf).commit();
}
mContent = df;
#Override
public void onItemSelected(String id) {
if (mTwoPane) {
// In two-pane mode, show the detail view in this activity by
// adding or replacing the detail fragment using a
// fragment transaction.
switch (Integer.valueOf(id)){
case 1:{
if (idf!=null){
getSupportFragmentManager().beginTransaction().hide(mContent).commit();
getSupportFragmentManager().beginTransaction().show(idf).commit();
mContent = idf;
}
}break;
case 2:{
if (df!=null){
getSupportFragmentManager().beginTransaction().hide(mContent).commit();
getSupportFragmentManager().beginTransaction().show(df).commit();
mContent = df;
}
}break;
}
} else {
// In single-pane mode, simply start the detail activity
// for the selected item ID.
Intent detailIntent = new Intent(this, ItemDetailActivity.class);
detailIntent.putExtra(ItemDetailFragment.ARG_ITEM_ID, id);
startActivity(detailIntent);
}
}
Problem:
With this approach, the Fragments hide/show without any problems and hold the status, but if I make an Orientation Change, they are destroyed and recreated again.
I know they are destroyed because I'm not using setRetainInstance(), but the problem is when I change orientation, the Activity loses the reference to the Fragment, and
df = (DevicesFragment) getSupportFragmentManager().findFragmentById(R.id.devices);
is null, so the program creates another Fragment. If I change the orientation again, not only the program re-creates two new Fragments, but two more Fragments are somehow added to the layout and they aren't even hidden, they are shown one above another.
If I use setRetainInstance(), the Fragment holds the state when Orientation is changed, but still, the activity reference to the Fragment is null, and creates a new Fragment above the existing one, having two of each Fragment.
Example:
I create Fragment A and Fragment B in Landscape orientation. Both work fine and I can switch between them.
I change orientation to Portrait, Fragment A and Fragment B are destroyed and a new Fragment A' and Fragment B' are created, still, they work fine.
I change orientation again to Landscape, Fragment A' and Fragment B' are destroyed, a new Fragment A'' and Fragment B'' are created, but the screen shows another Fragment A and Fragment B, both at the same time (one above another, let's call them residual), and these new A'' and B'' work fine but are shown above residual A and B.
From this point on, every time I change orientation, 2 new Fragments are added to the previous ones, but they don't even hold the previous state.
I hope the example is clear enough. I think the problem is the Activity not holding view references when the orientation is changed, creates them again and I don't really know how to work around that.
UPDATE:
I solved my problem by using findFragmentByTag instead of findFragmentById. Since I can now retrieve Fragment s already created, I have to add them to the container adding a specific tag to search for.
So my test code looks like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list);
if (findViewById(R.id.item_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-large and
// res/values-sw600dp). If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
// In two-pane mode, list items should be given the
// 'activated' state when touched.
((ItemListFragment) getSupportFragmentManager().findFragmentById(
R.id.item_list)).setActivateOnItemClick(true);
}
df = (DevicesFragment) getSupportFragmentManager().findFragmentByTag("df");
idf = (ItemDetailFragment) getSupportFragmentManager().findFragmentByTag("idf");
if (savedInstanceState==null){
if (df==null){
df = new DevicesFragment();
getSupportFragmentManager().beginTransaction().add(R.id.item_detail_container,df, "df").commit();
getSupportFragmentManager().beginTransaction().hide(df).commit();
}
if (idf==null){
idf = new ItemDetailFragment();
getSupportFragmentManager().beginTransaction().add(R.id.item_detail_container,idf,"idf").commit();
getSupportFragmentManager().beginTransaction().hide(idf).commit();
}
} else {
Log.i("OUT","INSTANCE NOT NULL");
}
mContent = df;
}
This is fully functional, also have to setRetainInstance(true) for every Fragment and they hold their current state no matter how many times we change the orientation.
You must never hold a reference to the fragment. Instead. Whenever you need something from it, retrieve the reference for a short moment.
public ItemListFragment getItemListFragment() {
return ((ItemListFragment) getSupportFragmentManager().findFragmentById(
R.id.item_list));
}
Then, whenever you need to get data from it, use
final ItemListFragment listFragment = getItemListFragment();
if (listFragment != null) {
// do something
}
And avoid calling setters. You can define the setters, but it's a better practice to either pass an arguments when creating a Fragment or retrieve the data by getActivity() from the Fragment itself, as described below.
This is done because the Fragment lifecycle not always matches the Activity one.
If you ever have to call setter from Activity, don't forget to save the value in Fragment's onSaveInstanceState(), if needed.
So instead of calling
setActivateOnItemClick(true);
From Activity, do it from the Fragment.
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final YourActivity activity = (Activtity) getYourActivity();
setActivateOnItemClick(activity.isMultiPane());
}
This way when the Fragment is re-created after Activity onCreate() (only in which you handle the value setting), it will has always access to the value
And define isMultiPane method from Activity, of course
public boolean isMultiPane() {
return mTwoPane;
}
Since there are no answer yet, here is my opinion :
When your orientation changes, your fragment is being recreated and you loose your data, right ? I think this is exactly whete the "savedInstanceState" is made for :
Caution: Your activity will be destroyed and recreated each time the user rotates the screen. When the screen changes orientation, the system destroys and recreates the foreground activity because the screen configuration has changed and your activity might need to load alternative resources (such as the layout).
Here is a link that can explain you how to handle that recreation
Hope this is useful to you ! =)

Single Activity with multiple fragments, typical scenario. Struggling to achieve desired behavior

I have an application running a single activity with multiple (2) fragments at a given time. I've got a fragment on the left which functions as a menu for which fragment to
display on the right hand side.
As an example lets say the menu consists of different sports; Football, Basketball, Baseball, Skiing, etc. When the user selects a sport, a fragment with details on the specific sport is displayed to the right.
I've set up my app to display two fragments at once in layout-large and layout-small-landscape. In layout-small-portrait however, only one fragment is displayed at a given time.
Imagine this; a user is browsing the app in layout-small-landscape (two fragments at a time) and selects a sport, Football. Shortly after he selects Basketball. If he now chooses to rotate into layout-small-portrait (one fragment at a time) I want the following to happen:
The Basketball fragment should be visible, but if he presses the back button, he should return to the menu and not to the Football fragment (!) which by default is the previous fragment in the back stack.
I have currently solved this like the following:
....
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// static fragments
if(menuFragment == null) menuFragment = new MenuFragment();
if(baseFragment == null) baseFragment = new TimerFragment(); // default content fragment
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// Determine what layout we're in..
if(app().getLayoutBehavior(this) == LayoutBehavior.SINGLE_FRAGMENT) {
// We are currently in single fragment mode
if(savedInstanceState != null) {
if(!rotateFromSingleToDual) {
// We just changed orientation from dual fragments to single fragment!
// Clear the entire fragment back stack
for(int i=0;i<getSupportFragmentManager().getBackStackEntryCount();i++) {
getSupportFragmentManager().popBackStack();
}
ft.replace(R.id.fragmentOne, menuFragment); // Add menu fragment at the bottom of the stack
ft.replace(R.id.fragmentOne, baseFragment);
ft.addToBackStack(null);
ft.commit();
}
rotateFromSingleToDual = true;
return;
}
rotateFromSingleToDual = true;
ft.replace(R.id.fragmentOne, menuFragment);
} else if(app().getLayoutBehavior(this) == LayoutBehavior.DUAL_FRAGMENTS) {
// We are now in dual fragments mode
if(savedInstanceState != null) {
if(rotateFromSingleToDual) {
// We just changed orientation from single fragment to dual fragments!
ft.replace(R.id.fragmentOne, menuFragment);
ft.replace(R.id.fragmentTwo, baseFragment);
ft.commit();
}
rotateFromSingleToDual = false;
return;
}
rotateFromSingleToDual = false;
ft.replace(R.id.fragmentOne, menuFragment);
ft.replace(R.id.fragmentTwo, baseFragment);
}
ft.commit();
}
This works, at least from time to time. However, many times I get java.lang.IllegalStateException: Fragment already added: MenuFragment (....)
Can anyone please give me some pointers as to how to better implement this? My current code is not pretty at all, and I'm sure many developers out there want to achieve exactly this.
Thanks in advance!
A common way to implement this scenario is to only use the fragment stack when in a mode that shows multiple fragments. When you're in the single fragment mode, you start a new activity that's sole job is to display the single fragment and take advantage of the activity back stack.
In your case you'll just need to remember the currently selected spot on rotate to set it as an argument when starting the new activity.
It's explained much better here:-
http://developer.android.com/guide/components/fragments.html
Hope that helps.

Categories

Resources