【问题标题】:Android Navigation Drawer Fragment StateAndroid 导航抽屉片段状态
【发布时间】:2014-08-02 22:03:11
【问题描述】:

我目前正在为我的 Android 应用程序使用导航抽屉。在我的第一个片段中,我有一个使用 Facebook 的 Graph API 加载数据的片段。因此,当我的 App 首次加载时,它首先会转到第一个片段。

然后,我使用导航抽屉单击另一个 Fragment 并查看它。

最后,我重用 Navigation Drawer 继续回到第一个 Fragment 并查看它。

我面临的问题是,我如何继续使用已创建一次的片段,而不是在选择导航抽屉项目时重新创建它。我的片段切换代码如下所示。

private void displayView(int position) {
    // update the main content by replacing fragments
    Fragment fragment = null;
    switch (position) {
    case 0:
        fragment = new SelectionFragment();
        break;
    case 1:
        fragment = new HomeFragment();
        break;
    case 2:
        fragment = new PhotosFragment();
        break;
    case 3:
        fragment = new CommunityFragment();
        break;
    case 4:
        fragment = new PagesFragment();
        break;
    case 5:
        fragment = new SplashFragment();
        break;
    default:
        break;
    }

    if (fragment != null) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.frame_container, fragment).commit();

        // update selected item and title, then close the drawer
        mDrawerList.setItemChecked(position, true);
        mDrawerList.setSelection(position);
        setTitle(navMenuTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
    } else {
        // error in creating fragment
        Log.e("MainActivity", "Error in creating fragment");
    }
}

我注意到每次选择该选项时确实有一个片段的“新”实例。如何实现创建 Fragment 实例 ONCE 并重用它的逻辑,这样我就不必一遍又一遍地不断加载 Fragment。

【问题讨论】:

  • 你有没有看到用 FragmentStatePagerAdapter 替换 ArrayAdapter 的特殊方法?我也想知道同样的问题,但还没有真正看到有人真正做到这一点,我也没有(我一直懒惰尝试,不是因为不可能。)

标签: android android-fragments android-fragmentactivity navigation-drawer


【解决方案1】:

对于和我遇到同样问题的人,我已经设法找到了解决方案。

在容器框架中,我必须定义我将使用的特定片段视图,如下所示。

在每个 Fragment 视图中,我必须通过 "android:name" 属性将其与实际 Fragment 本身“链接”,如下所示。请注意 路径 到 Fragment,例如在我的例子中是 com.example.confesssionsrp.SelectionFragment

<fragment
    android:id="@+id/selectionFragment"
    android:name="com.example.confessionsrp.SelectionFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

在 MainActivity(或我们正在查看 Fragment 的 Activity)中,为每个 Fragment 创建变量,如下所示。

然后,在MainActivity(或您的特定Activity)的Oncreate中,初始化各个片段,如下所示。

继续创建一个名为“ShowFragment”的新方法,如下所示。

private void showFragment(int fragmentIndex, boolean addToBackStack) {
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction transaction = fm.beginTransaction();
    for (int i = 0; i < fragments.length; i++) {
        if (i == fragmentIndex) {
            transaction.show(fragments[i]);
            if (Session.getActiveSession().isClosed()) {
                mDrawerLayout
                        .setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
            }
        } else {
            transaction.hide(fragments[i]);
        }
    }
    if (addToBackStack) {
        transaction.addToBackStack(null);
    }
    transaction.commit();
}

此后在Fragment的切换中,如下图所示,使用选中的Fragment手动调用“ShowFragment”方法。

整体完成所有这些操作,不会在每次查看片段时都重置片段,因此是答案的解决方案。感谢迄今为止帮助过我的任何人:)!

【讨论】:

  • 您的解决方案看起来非常好。我现在正在尝试...我会投票赞成。 :)
  • 我们不是通过创建所有片段来使应用程序变得繁重吗?
【解决方案2】:

我正在使用以下代码:

@Override
public void onNavigationDrawerItemSelected(int position) {

    // update the main content by replacing fragments
    FragmentManager fragmentManager = getFragmentManager();
    if(position==0){// selection of tabs content
        fragmentManager
        .beginTransaction()
        .replace(R.id.container,
                SimulatorFragment.newInstance(position + 1)).commit();
    }else if(position==1){
        fragmentManager
        .beginTransaction()
        .replace(R.id.container,
                HudFragment.newInstance(position + 1)).commit();
    }else if(position==2){
        // Display the fragment as the main content.
        fragmentManager
        .beginTransaction()
        .replace(R.id.container, 
                SettingsBasicFragment.newInstance(position +1)).commit();
    }else{

    }
}

你可以第一次用新实例替换并存储片段,如果不为空,则替换为存储的片段。

Activity 必须实现 NavigationDrawerFragment.NavigationDrawerCallbacks

片段构造函数和 newInstance 方法如下所示:

public final class HudFragment extends Fragment {
/**
 * The fragment argument representing the section number for this
 * fragment.
 */
private static final String ARG_SECTION_NUMBER = "section_number";

/**
 * Returns a new instance of this fragment for the given section number.
 * @param simulation 
 */
public static HudFragment newInstance(int sectionNumber) {  
    HudFragment fragment = new HudFragment();
    Bundle args = new Bundle();
    args.putInt(ARG_SECTION_NUMBER, sectionNumber);
    fragment.setArguments(args);
    return fragment;
}

public HudFragment() {
}

要通过代码切换片段,我在 NavigationDrawerFragment 中使用此方法:

/**
 * Select a different section
 * @param position
 */
public void select(int position){
    selectItem(position);
}

private void selectItem(int position) {
    mCurrentSelectedPosition = position;
    if (mDrawerListView != null) {
        mDrawerListView.setItemChecked(position, true);
    }            
    if (mDrawerLayout != null) {
        mDrawerLayout.closeDrawer(mFragmentContainerView);
    }
    if (mCallbacks != null) {
        mCallbacks.onNavigationDrawerItemSelected(position);
    }
}

【讨论】:

  • 嘿,谢谢你的帮助!我真的很感激。但我找到了另一种更简单的方法来实现它。再次感谢你的帮助伙伴! :)
【解决方案3】:

第二个选项是从 Android SDK 提供的 navigationDrawer 示例开始。我在创建项目时选择了该活动模板,并且我之前答案的几乎所有代码都是自动生成的。

如果您想在设备旋转或类似情况后保留片段,这是另一回事,您需要保留片段。如果没有,您只需将片段的新实例保存在一个变量中,并检查它是否为 null 以创建新实例或使用旧实例。

【讨论】:

    【解决方案4】:

    如果有人想要不同的方法:你可以在堆栈上找到片段:

    // check if this fragment is on the backstack to avoid creating a new one
        Fragment foundFragment =  fragmentManager.findFragmentByTag("unique_fragment_tag");
        if (foundFragment != null) {
              fragmentManager.popBackStackImmediate("unique_fragment_tag", 0);
                return;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多