根据Android guide报告,双窗格可以通过两种方式实现:
我正在使用第一个案例(Android指南仅解释了第二个案例)。
这是 7“平板电脑上发生的事情:
问题:为什么是单窗格片段(我以编程方式创建,但使用布局中定义的FrameLayout作为容器)在双窗格上重新创建?
我在下面的实施报告:
/layout/activity_main.xml:
<FrameLayout
android:id="@+id/single_pane"
android:layout_width="match_parent"
android:layout_height="match_parent" />
/layout-w900dp/activity_main.xml:
<LinearLayout
android:id="@+id/dual_pane"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.example.MasterFragment"
android:id="@+id/master_dual"
android:tag="MASTER_FRAGMENT_DUAL_PANE"
android:layout_width="@dimen/master_frag_width"
android:layout_height="match_parent"/>
<fragment class="com.example.DetailFragment"
android:id="@+id/detail_dual"
android:tag="DETAIL_FRAGMENT_DUAL_PANE"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
这是主要活动中的onCreate
:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDualPane = findViewById(R.id.dual_pane)!=null;
FragmentManager fm = getFragmentManager();
if (savedInstanceState==null) {
// this is a non-UI fragment I am using for data processing purposes
fm.beginTransaction().add(new NonUiFragment(), DATA_FRAGMENT).commit();
}
if (!mDualPane && fm.findFragmentById(R.id.single_pane)==null) {
fm.beginTransaction().add(R.id.single_pane, new MasterFragment(), MASTER_FRAGMENT_SINGLE_PANE).commit();
}
}
答案 0 :(得分:5)
我发现好多了在代码中为双窗格添加片段。
因此,代替使用<fragment>
,也可以将<FrameLayout>
用于双窗格XML。
/layout-w900dp/activity_main.xml:
<LinearLayout
android:id="@+id/dual_pane"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/master_dual"
android:layout_width="@dimen/master_frag_width"
android:layout_height="match_parent"/>
<FrameLayout
android:id="@+id/detail_dual"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
通过这种方式,您可以使用仅仅一个 masterFragment和DetailFragment的实例,因此您不会遇到同一个片段的多个实例的问题。
为了做到这一点,在OnCreate
中你需要将片段添加到容器中,从旧容器中分离出来:
mDualPane = findViewById(R.id.dual_pane)!=null;
if (savedInstanceState!=null) {
mLastSinglePaneFragment = savedInstanceState.getString("lastSinglePaneFragment");
}
FragmentManager fm = getSupportFragmentManager();
if (!mDualPane && fm.findFragmentById(R.id.single_pane)==null) {
MasterFragment masterFragment = 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) {
MasterFragment masterFragment = getDetatchedMasterFragment(true);
fm.beginTransaction().add(R.id.master_dual, masterFragment, MASTER_FRAGMENT).commit();
}
if (mDualPane && fm.findFragmentById(R.id.detail_dual)==null) {
DetailFragment detailFragment = getDetatchedDetailFragment();
fm.beginTransaction().add(R.id.detail_dual, detailFragment, DETAIL_FRAGMENT).commit();
}
使用这些功能:
public static final String MASTER_FRAGMENT = "MASTER_FRAGMENT";
public static final String DETAIL_FRAGMENT = "DETAIL_FRAGMENT";
private MasterFragment getDetatchedMasterFragment(boolean popBackStack) {
FragmentManager fm = getSupportFragmentManager();
MasterFragment masterFragment = getSupportFragmentManager().findFragmentByTag(MASTER_FRAGMENT);
if (masterFragment == null) {
masterFragment = new MasterFragment();
} else {
if (popBackStack) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
fm.beginTransaction().remove(masterFragment).commit();
fm.executePendingTransactions();
}
return masterFragment;
}
private DetailFragment getDetatchedDetailFragment() {
FragmentManager fm = getSupportFragmentManager();
DetailFragment detailFragment = getSupportFragmentManager().findFragmentByTag(DETAIL_FRAGMENT);
if (detailFragment == null) {
detailFragment = new DetailFragment();
} else {
fm.beginTransaction().remove(detailFragment).commit();
fm.executePendingTransactions();
}
return detailFragment;
}
private void openSinglePaneDetailFragment() {
FragmentManager fm = getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
DetailFragment detailFragment = getDetatchedDetailFragment();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.single_pane, detailFragment, DETAIL_FRAGMENT);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
答案 1 :(得分:0)
旋转时,当前活动的片段将由FragmentManager保存,并用于在创建新活动时自动重新创建片段。您可以通过不将savedInstanceState传递给super方法来阻止重新创建。例如。 super.onCreate(null);
。
或者,如果您需要使用FragmentActivity.onCreate(savedInstanceState)方法(调用FragmentManager.restoreAllState() - see https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/FragmentManager.java#L1759)恢复状态,您可以在onCreate中手动查找片段标记并将其删除。这是因为您有一个要恢复的非ui片段。保留片段的恢复还取决于使用saveInstanceState!= null调用FragmentActivity.onCreate(savedInstanceState)。
重新启动是因为通常您希望保留活动片段(并且可能在平板电脑的情况下添加第二个详细信息窗格)。
if (mDualPane) {
Fragment singlePane = getFragmentManager().findFragmentByTag(MASTER_FRAGMENT_SINGLE_PANE);
if (singlePane != null)
getFragmentManager().beginTransaction().remove(fragment).commit();
}