ActionBar Tab that contains fragments crashes when reshown
I have an SherlockFragmentActivity that uses an ActionBar with tabs. One of those tabs is an SherlockFragment that has a layout file that includes an fragment. When that tab is first shown, all is great. If I switch to another tab and then back to that tab, I get a crash:
02-21 10:25:10.077: E/AndroidRuntime(3916): Caused by: java.lang.IllegalArgumentException: Binary XML file line #29: Duplicate id 0x7f06006e, tag null, or parent id 0x0 with another fragment for com.nexapps.myq.fragments.TitleInfo 02-21 10:25:10.077: E/AndroidRuntime(3916): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:275) 02-21 10:25:10.077: E/AndroidRuntime(3916): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676) 02-21 10:25:10.077: E/AndroidRuntime(3916): ... 21 more
My main activity:
public class TitleActivity extends SherlockFragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
...
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
...
Tab tab = actionBar.newTab().setText(R.string.details);
tab.setTabListener(new TabListener<TitleDetailsFragment>(this, "details", TitleDetailsFragment.class));
actionBar.addTab(tab);
}
}
Tab Listener: public class TabListener implements com.actionbarsherlock.app.ActionBar.TabListener { private Fragment mFragment; private final Activity mActivity; private final String mTag; private final Class mClass;
public TabListener(Activity activity, String tag, Class<T> cls) {
mActivity = activity;
mTag = tag;
mClass = cls;
}
public TabListener(Activity activity, String tag, Class<T> clz, Fragment fragment) {
mActivity = activity;
mTag = tag;
mClass = clz;
mFragment = fragment;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (mFragment == null) {
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, mTag);
} else {
ft.attach(mFragment);
}
TabChangeInterface tci = (TabChangeInterface) mActivity;
if (tci != null) {
tci.tabSelect(mTag);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
ft.detach(mFragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
My Tab fragment:
public class TitleDetailsFragment extends SherlockFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_title, container, false);
return view;
}
}
R.layout.activity_title:
<fragment
android:id="@+id/info"
android:name="foo.TitleInfo"
...
I could remove the id (which fixes the issue) but those help with state changes. Any thoughts on how to keep the ids and fix the issue?
You cannot remove fragments that are embedded in an xml layout. For that, you should change your xml to include a <FrameLayout android:id="fragment_container" .../>
and then programmatically replace the fragments in the frame by calling:
MyFrag newFragment = new MyFrag();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container,newFragment,"myFragName")
.addToBackStack("myFragName")//optional
.commit();
Assuming you are using support package, otherwise you just change getSupportFragmentManager()
to getFragmentManager()
And you can read more about using fragments here: http://developer.android.com/training/basics/fragments/index.html
EDIT: Updated to include code based on new information
R.layout.activity_title:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Title" >
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
TitleActivity.class:
public class TitleActivity extends SherlockFragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_title);
...
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
...
Tab tab = actionBar.newTab().setText(R.string.details);
tab.setTabListener(new TabListener<TitleDetailsFragment>(this, "details", TitleDetailsFragment.class));
actionBar.addTab(tab);
}
}
R.layout.details_fragment:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:textSize="10sp"
android:textStyle="italic"
android:text="Details are here!"/>
</RelativeLayout>
TabFragment:
public class TitleDetailsFragment extends SherlockFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.details_fragment, container, false);
}
}
TabListener you can keep the same as your code above.
So this has to do with the fact that tab contents are a fragment, and fragments can't contain fragments. So use views instead here or manually remove/add using transactions.
链接地址: http://www.djcxy.com/p/78914.html