Helo.
I read a lot here and on other sites, but it seems that no one have a working solution for using fragments as wizard like app.
I try to implement one, but got some problems at the moment.
Here is the Activity XML with placeholder for Step-Fragments:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/cmd_previous"
android:layout_alignParentTop="true" >
</FrameLayout>
<Button
android:id="@+id/cmd_previous"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignRight="@+id/center_separator_buttons"
android:text="@string/rpz_cmd_perv" />
<View
android:id="@+id/center_separator_buttons"
style="@style/wd_center_aligner"
android:layout_alignParentBottom="true" />
<Button
android:id="@+id/cmd_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/center_separator_buttons"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="@string/rpz_cmd_next" />
</RelativeLayout>
In OnCreate I add the first step to the activity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_report_wizard);
if (this.getIntent().getExtras() != null) {
Bundle extra = this.getIntent().getExtras();
if (extra.containsKey(ISelected.ID_KEY)) {
_ID = extra.getLong(ISelected.ID_KEY);
}
}
if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) {
_ReportTypeAndName = new ReportWizardTypeAndNameFragment();
_ReportTypeAndName.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, _ReportTypeAndName).commit();
}
}
The NEXT-button replace the current Fragment with new one. This seems to work fine.
private void runNext(View view) {
switch (_CurrentPage) {
case ReportTypeAndName:
_ReportSelect = new ReportWizardSelectFragment();
_ReportSelect.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, _ReportSelect).addToBackStack(null).commit();
_CurrentPage = ReportWizardPage.ReportSelect;
break;
case ReportSelect:
_CurrentPage = ReportWizardPage.ReportPreview;
break;
case ReportPreview:
_CurrentPage = ReportWizardPage.None;
break;
default:
break;
}
}
But on the PREVIOUS-Button, this doesn't work.
private void runPrevious(View view) {
switch (_CurrentPage) {
case ReportTypeAndName:
// Umstellung des Typs
_CurrentPage = ReportWizardPage.None;
this.finish();
break;
case ReportSelect:
_ReportTypeAndName = new ReportWizardTypeAndNameFragment();
_ReportTypeAndName.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, _ReportTypeAndName).commit();
_CurrentPage = ReportWizardPage.ReportTypeAndName;
break;
case ReportPreview:
_CurrentPage = ReportWizardPage.ReportSelect;
break;
default:
break;
}
}
I got the following Error (LogCat):
FATAL EXCEPTION: main
android.view.InflateException: Binary XML file line #13: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:697)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:739)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at de.webducer.android.worktime.beta.ui.fragment.ReportWizardTypeAndNameFragment.onCreateView(ReportWizardTypeAndNameFragment.java:40)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:870)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1080)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:622)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1416)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:420)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException: Binary XML file line #13: Duplicate id 0x7f05008b, tag null, or parent id 0x0 with another fragment for de.webducer.android.worktime.beta.ui.fragment.ReportTypeSelectorSpinnerFragment
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:275)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:669)
... 18 more
The line 40 of the Fragment is the inflater of them
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.frag_report_wizard_1, container, false);
}
How can I bind (add/remove) the fragments without getting duplicate IDs? Or how can I reuse the fragment without new View-Initialization?
Best Answer
Put your fragments in the backstack and call them back as needed.
Add it to the backstack using
addToBackStack
:Pull it back up using
popBackStack
:Note this code came from an app of mine using the v4 support library, so the call for the fragment manager will be slightly different if you are developing for Android 3.0+ only.