OnBackPressed 不跟随 backstack;直接转到主页片段
OnBackPressed not following backstack; goes directly to home Fragment
我很困惑,不明白发生了什么。我的应用程序使用带有关闭 window 和主屏幕检查的 OnBackPressed,简而言之 "if home, else, use exit menu"
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (!viewIsAtHome) {
displayView(R.id.nav_large_monsters);
} else {
new AlertDialog.Builder(this)
.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Home.this.finish();
}
})
.setNegativeButton("No", null)
.show();
}
}
正在发生但我不想发生的事情是 按下后退会直接将我带回我的 "Large Monsters" 片段。我想让它跟在后台。
我在大型怪物页面上有大约 30 个按钮可以带你进入怪物的信息,但是按下后退会立即弹出 "Are you sure you want to quit" 菜单,而不是返回到大型怪物碎片:
Large Monsters
Pressing Back button from a Monster fragment
很明显它没有跟随后退堆栈。与任何其他屏幕一样,如果我转到任何其他片段,它会直接带我回到 Nav_Large_Monsters 而不是跟随后退堆栈。
我假设我的问题是这样的:
} else if (!viewIsAtHome) {
displayView(R.id.nav_large_monsters);
但是如果我删除它,应用程序会立即要求退出,而不是return home,仍然没有跟随backstack。
如果我 return 将 onBackPressed 返回到其默认代码,它将跟随 backstack,但它不会加载主页片段并以空白片段开始。
已尝试:
我试图删除 onBackPressed 中的“else if (!viewIsAtHome)”部分,并在我的 onNavigationItemSelected 方法中实现了 "default"
default:
fragment = new Large_Monsters();
break;
这也行不通。不加载主页片段。
以前我有一个 showHome() 方法,这个 DID 可以使用 backStack 和 home 片段,但是在将我的片段更改为 v4.support.app.Fragment 之后,我有改变我的主页 Activity 处理我的 onNavigationItemSelected 的方式。它 不喜欢 我的 showHome 方法,并一直说我使用的是旧的 FragmentManager 而不是 v4.support.app.FragmentManager(此方法导致我的应用程序在更改为 v4 后立即崩溃) :
private void showHome() {
fragment = new Large_Monsters();
if (fragment != null) {
android.app.FragmentManager fragMgmt = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
}
}
我还尝试添加一个关于弹出 backStack 的 If 语句,但这似乎没有做任何有成效的事情:
if (!fragment.getFragmentManager().popBackStackImmediate()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
finishAfterTransition();
}
}
我还尝试添加一个 If 语句来检查 Backstack 是否 > 0,但这也没有帮助,尽管我删除了那个字符串并且不确定我在哪里找到它。也许我构建的那个字符串不正确。
任何帮助都会很棒!谢谢!
代码:
Home.java(MainActivity,我只是在这个项目上将它命名为 Home)
public class Home extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private Fragment fragment = null;
private FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DatabaseHelper myDbHelper = new DatabaseHelper(Home.this);
try {
myDbHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
navigationView.setItemIconTintList(null);
// showHome();
displayView(R.id.nav_large_monsters);
}
private boolean viewIsAtHome;
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (!viewIsAtHome) {
displayView(R.id.nav_large_monsters);
} else {
new AlertDialog.Builder(this)
.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Home.this.finish();
}
})
.setNegativeButton("No", null)
.show();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
return super.onOptionsItemSelected(item);
}
// private void showHome() {
// fragment = new Large_Monsters();
// if (fragment != null) {
// android.app.FragmentManager fragMgmt = getFragmentManager();
// fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// }
// }
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
displayView(item.getItemId());
return true;
}
public void displayView(int viewId) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (viewId) {
case R.id.nav_large_monsters:
fragment = new Large_Monsters();
title = "Large Monsters";
viewIsAtHome = true;
break;
case R.id.nav_small_monsters:
fragment = new Small_Monsters();
title = "Small Monsters";
viewIsAtHome = false;
break;
case R.id.nav_weapons:
fragment = new Weapons();
title = "Weapons";
viewIsAtHome = false;
break;
case R.id.nav_armors:
fragment = new Armors_Low_High();
title = "Armor Sets";
viewIsAtHome = false;
break;
case R.id.nav_charms:
fragment = new Charms();
title = "Charms";
viewIsAtHome = false;
break;
case R.id.nav_items:
fragment = new Items();
title = "Items";
viewIsAtHome = false;
break;
case R.id.palico_armor:
fragment = new Palico_Armor();
title = "Palico Armor";
viewIsAtHome = false;
break;
case R.id.palico_gadgets:
fragment = new Palico_Gadgets();
title = "Palico Gadgets";
viewIsAtHome = false;
break;
case R.id.palico_weps:
fragment = new Palico_Weapons();
title = "Palico Weapons";
viewIsAtHome = false;
break;
case R.id.palico_helms:
fragment = new Palico_Helms();
title = "Palico Helmets";
viewIsAtHome = false;
break;
default:
fragment = new Large_Monsters();
break;
}
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment, fragment.getTag())
.addToBackStack(null);
ft.commit();
}
// set the toolbar title
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(title);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
}
}
如果您要覆盖 onBackPressed
,您必须自己处理回溯的撤消。这是 FragmentActivity
的作用:
/**
* Take care of popping the fragment back stack or finishing the activity
* as appropriate.
*/
@Override
public void onBackPressed() {
FragmentManager fragmentManager = mFragments.getSupportFragmentManager();
final boolean isStateSaved = fragmentManager.isStateSaved();
if (isStateSaved && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
// Older versions will throw an exception from the framework
// FragmentManager.popBackStackImmediate(), so we'll just
// return here. The Activity is likely already on its way out
// since the fragmentManager has already been saved.
return;
}
if (isStateSaved || !fragmentManager.popBackStackImmediate()) {
super.onBackPressed();
}
}
如果您跳过它,您将不会出现片段弹出行为。因此,只需更新您的 onBackPressed
以包含片段管理器的弹出 - 如果成功,您可以提前 return 因为系统会根据需要弹出片段。
@Override
public void onBackPressed() {
// Pressing back popped the back stack, nothing else to do
FragmentManager fragmentManager = getSupportFragmentManager();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (!fragmentManager.isStateSaved() && fragmentManager.popBackStackImmediate()) {
return;
} else {
new AlertDialog.Builder(this)
.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Home.this.finish();
}
})
.setNegativeButton("No", null)
.show();
}
}
更新
您还需要更新您的 displayView
方法,因为现在它总是 将某些东西压入堆栈。因此,您的 "home" 片段实际上将成为堆栈中的第一件事,并且会弹出并留下一个空白屏幕。因此,如果您要显示 "home" 片段,不要 在片段管理器上调用 addToBackStack
。
此外,您不需要在按下时显式设置 "home" 片段,因为弹出 backstack 应该做正确的事情(参见上面更新的示例)。
希望对您有所帮助!
我很困惑,不明白发生了什么。我的应用程序使用带有关闭 window 和主屏幕检查的 OnBackPressed,简而言之 "if home, else, use exit menu"
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (!viewIsAtHome) {
displayView(R.id.nav_large_monsters);
} else {
new AlertDialog.Builder(this)
.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Home.this.finish();
}
})
.setNegativeButton("No", null)
.show();
}
}
正在发生但我不想发生的事情是 按下后退会直接将我带回我的 "Large Monsters" 片段。我想让它跟在后台。
我在大型怪物页面上有大约 30 个按钮可以带你进入怪物的信息,但是按下后退会立即弹出 "Are you sure you want to quit" 菜单,而不是返回到大型怪物碎片:
Large Monsters
Pressing Back button from a Monster fragment
很明显它没有跟随后退堆栈。与任何其他屏幕一样,如果我转到任何其他片段,它会直接带我回到 Nav_Large_Monsters 而不是跟随后退堆栈。
我假设我的问题是这样的:
} else if (!viewIsAtHome) {
displayView(R.id.nav_large_monsters);
但是如果我删除它,应用程序会立即要求退出,而不是return home,仍然没有跟随backstack。
如果我 return 将 onBackPressed 返回到其默认代码,它将跟随 backstack,但它不会加载主页片段并以空白片段开始。
已尝试:
我试图删除 onBackPressed 中的“else if (!viewIsAtHome)”部分,并在我的 onNavigationItemSelected 方法中实现了 "default"
default: fragment = new Large_Monsters(); break;
这也行不通。不加载主页片段。
以前我有一个 showHome() 方法,这个 DID 可以使用 backStack 和 home 片段,但是在将我的片段更改为 v4.support.app.Fragment 之后,我有改变我的主页 Activity 处理我的 onNavigationItemSelected 的方式。它 不喜欢 我的 showHome 方法,并一直说我使用的是旧的 FragmentManager 而不是 v4.support.app.FragmentManager(此方法导致我的应用程序在更改为 v4 后立即崩溃) :
private void showHome() { fragment = new Large_Monsters(); if (fragment != null) { android.app.FragmentManager fragMgmt = getFragmentManager(); fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit(); }
}
我还尝试添加一个关于弹出 backStack 的 If 语句,但这似乎没有做任何有成效的事情:
if (!fragment.getFragmentManager().popBackStackImmediate()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { finishAfterTransition(); } }
我还尝试添加一个 If 语句来检查 Backstack 是否 > 0,但这也没有帮助,尽管我删除了那个字符串并且不确定我在哪里找到它。也许我构建的那个字符串不正确。
任何帮助都会很棒!谢谢!
代码:
Home.java(MainActivity,我只是在这个项目上将它命名为 Home)
public class Home extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private Fragment fragment = null;
private FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DatabaseHelper myDbHelper = new DatabaseHelper(Home.this);
try {
myDbHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
navigationView.setItemIconTintList(null);
// showHome();
displayView(R.id.nav_large_monsters);
}
private boolean viewIsAtHome;
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (!viewIsAtHome) {
displayView(R.id.nav_large_monsters);
} else {
new AlertDialog.Builder(this)
.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Home.this.finish();
}
})
.setNegativeButton("No", null)
.show();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
return super.onOptionsItemSelected(item);
}
// private void showHome() {
// fragment = new Large_Monsters();
// if (fragment != null) {
// android.app.FragmentManager fragMgmt = getFragmentManager();
// fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// }
// }
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
displayView(item.getItemId());
return true;
}
public void displayView(int viewId) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (viewId) {
case R.id.nav_large_monsters:
fragment = new Large_Monsters();
title = "Large Monsters";
viewIsAtHome = true;
break;
case R.id.nav_small_monsters:
fragment = new Small_Monsters();
title = "Small Monsters";
viewIsAtHome = false;
break;
case R.id.nav_weapons:
fragment = new Weapons();
title = "Weapons";
viewIsAtHome = false;
break;
case R.id.nav_armors:
fragment = new Armors_Low_High();
title = "Armor Sets";
viewIsAtHome = false;
break;
case R.id.nav_charms:
fragment = new Charms();
title = "Charms";
viewIsAtHome = false;
break;
case R.id.nav_items:
fragment = new Items();
title = "Items";
viewIsAtHome = false;
break;
case R.id.palico_armor:
fragment = new Palico_Armor();
title = "Palico Armor";
viewIsAtHome = false;
break;
case R.id.palico_gadgets:
fragment = new Palico_Gadgets();
title = "Palico Gadgets";
viewIsAtHome = false;
break;
case R.id.palico_weps:
fragment = new Palico_Weapons();
title = "Palico Weapons";
viewIsAtHome = false;
break;
case R.id.palico_helms:
fragment = new Palico_Helms();
title = "Palico Helmets";
viewIsAtHome = false;
break;
default:
fragment = new Large_Monsters();
break;
}
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction()
.replace(R.id.content_frame, fragment, fragment.getTag())
.addToBackStack(null);
ft.commit();
}
// set the toolbar title
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle(title);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
}
}
如果您要覆盖 onBackPressed
,您必须自己处理回溯的撤消。这是 FragmentActivity
的作用:
/**
* Take care of popping the fragment back stack or finishing the activity
* as appropriate.
*/
@Override
public void onBackPressed() {
FragmentManager fragmentManager = mFragments.getSupportFragmentManager();
final boolean isStateSaved = fragmentManager.isStateSaved();
if (isStateSaved && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
// Older versions will throw an exception from the framework
// FragmentManager.popBackStackImmediate(), so we'll just
// return here. The Activity is likely already on its way out
// since the fragmentManager has already been saved.
return;
}
if (isStateSaved || !fragmentManager.popBackStackImmediate()) {
super.onBackPressed();
}
}
如果您跳过它,您将不会出现片段弹出行为。因此,只需更新您的 onBackPressed
以包含片段管理器的弹出 - 如果成功,您可以提前 return 因为系统会根据需要弹出片段。
@Override
public void onBackPressed() {
// Pressing back popped the back stack, nothing else to do
FragmentManager fragmentManager = getSupportFragmentManager();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (!fragmentManager.isStateSaved() && fragmentManager.popBackStackImmediate()) {
return;
} else {
new AlertDialog.Builder(this)
.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Home.this.finish();
}
})
.setNegativeButton("No", null)
.show();
}
}
更新
您还需要更新您的 displayView
方法,因为现在它总是 将某些东西压入堆栈。因此,您的 "home" 片段实际上将成为堆栈中的第一件事,并且会弹出并留下一个空白屏幕。因此,如果您要显示 "home" 片段,不要 在片段管理器上调用 addToBackStack
。
此外,您不需要在按下时显式设置 "home" 片段,因为弹出 backstack 应该做正确的事情(参见上面更新的示例)。
希望对您有所帮助!