Android: Master/detail Flow (dual-pane) Using 1 Activity
Solution 1:
I found it's much better to add the fragments in the code also for the dual pane.
So, instead of using the <fragment>
, also use the <FrameLayout>
also for the dual-pane XML.
/layout-w900dp/activity_main.xml:
<LinearLayoutandroid:id="@+id/dual_pane"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><FrameLayoutandroid:id="@+id/master_dual"android:layout_width="@dimen/master_frag_width"android:layout_height="match_parent"/><FrameLayoutandroid:id="@+id/detail_dual"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>
In this way, you can use just one instance of the masterFragment and of the DetailFragment, so you don't fall into the problem of having multiple instances of the same fragment.
In order to do this, in the OnCreate
you need to add the fragments to the container, detaching from the old container:
mDualPane = findViewById(R.id.dual_pane)!=null;
if (savedInstanceState!=null) {
mLastSinglePaneFragment = savedInstanceState.getString("lastSinglePaneFragment");
}
FragmentManagerfm= getSupportFragmentManager();
if (!mDualPane && fm.findFragmentById(R.id.single_pane)==null) {
MasterFragmentmasterFragment= getDetatchedMasterFragment(false);
fm.beginTransaction().add(R.id.single_pane, masterFragment, MASTER_FRAGMENT).commit();
if (mLastSinglePaneFragment==DETAIL_FRAGMENT) {
openSinglePaneDetailFragment();
}
}
if (mDualPane && fm.findFragmentById(R.id.master_dual)==null) {
MasterFragmentmasterFragment= getDetatchedMasterFragment(true);
fm.beginTransaction().add(R.id.master_dual, masterFragment, MASTER_FRAGMENT).commit();
}
if (mDualPane && fm.findFragmentById(R.id.detail_dual)==null) {
DetailFragmentdetailFragment= getDetatchedDetailFragment();
fm.beginTransaction().add(R.id.detail_dual, detailFragment, DETAIL_FRAGMENT).commit();
}
using these functions:
publicstaticfinalStringMASTER_FRAGMENT="MASTER_FRAGMENT";
publicstaticfinalStringDETAIL_FRAGMENT="DETAIL_FRAGMENT";
private MasterFragment getDetatchedMasterFragment(boolean popBackStack) {
FragmentManagerfm= getSupportFragmentManager();
MasterFragmentmasterFragment= getSupportFragmentManager().findFragmentByTag(MASTER_FRAGMENT);
if (masterFragment == null) {
masterFragment = newMasterFragment();
} else {
if (popBackStack) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
fm.beginTransaction().remove(masterFragment).commit();
fm.executePendingTransactions();
}
return masterFragment;
}
private DetailFragment getDetatchedDetailFragment() {
FragmentManagerfm= getSupportFragmentManager();
DetailFragmentdetailFragment= getSupportFragmentManager().findFragmentByTag(DETAIL_FRAGMENT);
if (detailFragment == null) {
detailFragment = newDetailFragment();
} else {
fm.beginTransaction().remove(detailFragment).commit();
fm.executePendingTransactions();
}
return detailFragment;
}
privatevoidopenSinglePaneDetailFragment() {
FragmentManagerfm= getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
DetailFragmentdetailFragment= getDetatchedDetailFragment();
FragmentTransactionfragmentTransaction= fm.beginTransaction();
fragmentTransaction.replace(R.id.single_pane, detailFragment, DETAIL_FRAGMENT);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
Solution 2:
When you rotate, the currently active fragments will be saved by the FragmentManager and used to recreate fragments automatically when the new Activity is created. You can prevent recreation by not passing the savedInstanceState to the super method. E.g. super.onCreate(null);
.
Alternatively if you need to restore state using the FragmentActivity.onCreate(savedInstanceState) method (which calls FragmentManager.restoreAllState() —see https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/FragmentManager.java#L1759), you can lookup your fragment tag and remove it manually in your onCreate. This is the case since you have a non-ui Fragment you want to restore. The restoration of retained fragments also depends on the call to FragmentActivity.onCreate(savedInstanceState) with saveInstanceState != null.
The recreation happens because usually you want to keep the active fragment around (and possibly add a second detail pane in the case of tablets).
if (mDualPane) {
Fragment singlePane = getFragmentManager().findFragmentByTag(MASTER_FRAGMENT_SINGLE_PANE);
if (singlePane != null)
getFragmentManager().beginTransaction().remove(fragment).commit();
}
Post a Comment for "Android: Master/detail Flow (dual-pane) Using 1 Activity"