Android:使用1个活动的主/明细流(双窗格) [英] Android: master/detail flow (dual-pane) using 1 activity

查看:165
本文介绍了Android:使用1个活动的主/明细流(双窗格)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Android指南双窗格可以通过两种方式实现:

As reported by the Android guide, dual-pane can be achieved in two ways:

  1. 多个片段,一个活动
  2. 多个片段,多个活动
  1. Multiple fragments, one activity
  2. Multiple fragments, multiple activities

我正在使用第一种情况(Android指南仅说明了第二种情况).

I am using the first case (the Android guide only explains the second case).

这是在 7英寸平板电脑上发生的事情:

  • 从横向旋转到纵向:仅重新创建单窗格片段
  • 从纵向旋转到横向:重新创建所有3个片段(单窗格,双窗格母版,双窗格细节)
  • rotating from landscape to portrait: only the single-pane fragment gets recreated
  • rotating from portrait to landscape: all 3 fragments (single-pane, dual-pane-master, dual-pane-detail) get recreated

问题:为什么是单窗格片段(我以编程方式创建,但是使用布局中定义的FrameLayout作为容器)在双窗格中重新创建了?

Question: why is the single-pane fragment (which I create programmatically, but using a FrameLayout defined in the layout as the container) get recreated on dual pane?

我在执行以下报告:

/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();
    }
}

推荐答案

我发现将代码片段也添加到双窗格中更好.

I found it's much better to add the fragments in the code also for the dual pane.

因此,对于双窗格XML,也不要使用<fragment>,也要使用<FrameLayout>.

So, instead of using the <fragment>, also use the <FrameLayout> also for the dual-pane 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>

通过这种方式,您可以只使用master片段和DetailFragment的一个实例.这样就不会出现具有相同片段的多个实例的问题.

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.

为此,在OnCreate中,您需要将片段添加到容器中,并与旧容器分离:

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");
    }

    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();
}

这篇关于Android:使用1个活动的主/明细流(双窗格)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆