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();
}
我发现很多 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();
}