如何在导航抽屉活动中实现屏幕旋转时保持相同的片段?

6
我发现很多文章都解释了如何从savedInstanceState Bundle中获取Fragment,但是因为Activity可以在4个Fragments之间切换,所以我需要一种方法在方向开始改变时知道哪个Fragment是活动的。我有几个Fragments的原因是我正在使用Navigation Drawer,每个菜单项都作为一个Fragment。

我发现很多帖子都解释了如何从savedInstanceState Bundle中获取Fragment - 真的吗?在Activity中,您可以在onPause()之后调用isChangingConfigurations()方法来查找是否正在发生配置更改。虽然不完全符合您的要求,但如果正在发生配置更改,则此方法将返回true,否则返回false,即Activity正在被销毁而不是重新创建。 - Mark
当屏幕方向发生变化时,系统会负责将Fragment显示为前一个Activity中的状态,即您的Activity被销毁,但FragmentManager不会被销毁。一旦新的Activity被创建,它将负责将这些Fragment添加到新创建的Activity中。您具体遇到了什么问题? - azizbekian
3个回答

7

我遇到了同样的问题,通过在导航抽屉活动代码中添加以下内容来解决:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(savedInstanceState==null){
        //Handle the initial fragment transaction
    }
    ...
}

例如,我有一个导航抽屉,其中的菜单项为“主页”,“设置”和“关于”,每个菜单项对应一个名为“home_fragment”,“settings_fragment”和“about_fragment”的片段。
如果我希望在导航抽屉活动启动时出现“home_fragment”,我可以在OnCreate函数中使用以下代码:
FragmentManager fM = getSupportFragmentManager();
fM.beginTransaction().replace(R.id.NavDrawContent,new home_fragment()).commit();

但我希望它只在(savedInstanceState == null)时执行,这样当我们在settings_fragment(例如)中更改手机方向时,它不会膨胀home_fragment。

因此,在导航抽屉活动OnCreate中的最终代码:

super.onCreate(savedInstanceState);
if(savedInstanceState==null){
    FragmentManager fM = getSupportFragmentManager();
    fM.beginTransaction().replace(R.id.NavDrawContent,new home_fragment()).commit();
}

3
在活动中,您在onSaveInstanceState()中保存片段的实例并在onCreate()中进行恢复。
@Override
public void onCreate(Bundle savedInstanceState) {
    ...
    if (savedInstanceState != null) {     
        fragment = getSupportFragmentManager().getFragment(savedInstanceState, "KEY");
        changeFragment(fragment, "MY TAG")
    } else {
        setupFragment();
    }
    ...
}


@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    Fragment fragment = getSupportFragmentManager().findFragmentByTag("MY TAG");
    if (fragment != null) {
        getSupportFragmentManager().putFragment(outState, "KEY", fragment);
    }
}

如果您需要知道哪个片段已保存,可以使用instanceof进行检查,例如:
if (fragment instanceof SettingsFragment) {
    // ...
}

当调用 onSaveInstanceState 时,我需要保存的是片段的类,或者告诉我当前活动的片段是什么。导航抽屉在用户选择导航菜单上的另一个选项时交换片段。 - MiguelSlv
你可以使用 fragment.getClass().getSimpleName() 来获取类名。outState.putString("CLASS", fragment.getClass().getSimpleName()); - Jean Pimentel

-1

我找到了自己的答案,其实这是一件非常简单的事情。我在这里留下解决方案,供那些像我一样不熟悉安卓的人参考。

//current fragment
int fragment_id;

//make fragment selection available form the menu resource id
private void setFragment(MenuItem item) {

    Fragment fragment = null;
    fragment_id = item.getItemId();

    switch (fragment_id) {
        case R.id.nav_option_1:
            fragment = MyFragment1.newInstance(true);
            break;
        ...
        //Set fragment
        FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.replace(R.id.content_navigation, fragment);
        t.commit();
    }

    item.setChecked(true);
}

private class DrawerItemClickListener implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        setFragment(item);
        return false;
    }
}

//save the state
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(SAVE_INSTANCE_FRAGMENT_KEY, fragmentid);
}

//restore the saved fragment on create
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_navigation);
    ///...
    if (savedInstanceState != null) {
        int fragment_id = savedInstanceState.getInt(SAVE_INSTANCE_FRAGMENT_KEY);
        selectItem(mDrawerList.getMenu().findItem(fragment_id));
    } else {
        selectItem(mDrawerList.getMenu().findItem(R.id.home_fragment_id));
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接