activity 由于导航抽屉 Activity 中的方向更改而重新启动时如何保持相同的片段

How to keep the same fragment when activity restarts due to orientation change in a Navigation Drawer Activity

我发现很多 post 解释如何从 savedInstanceState Bundle 得到 Fragment 但是,因为 Activity 可以在 4 [=16] 之间交换=],我需要一种方法来知道哪个 Fragment 还活着,然后在方向开始改变时旋转。

我有多个片段的原因是因为我使用的是导航抽屉,所以每个菜单项都是一个片段。

在 activity 中,您将片段的实例保存在 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) {
    // ...
}

找到了我自己的答案,毕竟这是一件非常简单的事情。我把解决方案留给那些不熟悉 android 的人,比如我。

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

}

我遇到了同样的问题,我将其添加到导航抽屉 activity 代码中修复了它:

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

例如,我有一个带有 "Home"、"Settings" 和 "About" 作为菜单项的导航抽屉,每个菜单项都有一个片段 "home_fragment"、"settings_fragment"和 "about_fragment".

如果我希望 "home_fragment" 在导航抽屉 activity 启动时出现,我在 OnCreate 函数上使用此代码:

FragmentManager fM = getSupportFragmentManager();
fM.beginTransaction().replace(R.id.NavDrawContent,new home_fragment()).commit();

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

所以最后的代码(在导航抽屉里 activity OnCreate):

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