Android双击返回关闭有碎片的应用程序
Android Double Back Press to close the app having fragments
我在 SO 上关注了 this tutorial 和某些类似的答案。
我现在的onBackPressed
代码如下-
private static final int TIME_DELAY = 2000;
private static long back_pressed;
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
int fragments = getFragmentManager().getBackStackEntryCount();
if (fragments > 0) {
super.onBackPressed();
} else {
if (back_pressed + TIME_DELAY > System.currentTimeMillis()) {
super.onBackPressed();
} else {
Toast.makeText(getBaseContext(), "Press once again to exit!",
Toast.LENGTH_SHORT).show();
}
back_pressed = System.currentTimeMillis();
}
}
}
我正在像这样将片段添加到后台堆栈(在某些地方我不添加到后台堆栈)-
private void LoadSignDetailsFragment() {
Bundle args = new Bundle();
Fragment fragment = new SignDetailsFragment();
args.putBoolean("hasValues", true);
args.putBoolean("showBookmarkedSignsOnly", showBookmarkedSignsOnly);
args.putInt("sign_id", signId);
if (fragment != null) {
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragment.setArguments(args);
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit);
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
我想做的是,如果后台堆栈中有任何片段,单个 onBackPressed
迁移到前一个片段。但是,如果backstack中没有Fragment,它应该显示Toast,双击后退关闭应用程序。
我现在的代码,总是显示 Toast,并要求双回按,而不考虑后台堆栈中的 presence/absence 个片段。我想不通为什么?
以简单的方式做到这一点
使用下面的代码
Boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
System.exit(0);
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Please click BACK again to exit",
Toast.LENGTH_SHORT).show();
}
将此代码添加到您的 onCreateView 片段中
view.setOnKeyListener( new OnKeyListener()
{
private Boolean exit = false;
@Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
//logic for identifying double back press, expires after 3 seconds
if (exit) {
getActivity().finish(); // finish activity
} else {
Toast.makeText(this, "Press Back again to Exit.",
Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
exit = false;
}
}, 3 * 1000);
}
return true;
}
return false;
}
} );
或者如果你想在 activity 中添加它,你必须重写 onBackPressed 方法并添加相同的代码。
例子
private Boolean exit = false;
@Override
public void onBackPressed(){
if (exit) {
finish(); // finish activity
} else {
Toast.makeText(this, "Press Back again to Exit.",
Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
exit = false;
}
}, 3 * 1000);
}
}
但建议在 activity 中执行,而不是片段
您可以根据需要参考以下代码。如果您不使用 v4 支持片段,则必须使用 getFragmentManager()
而不是 getSupportFragmentManager()
来获取后台堆栈计数。这里我是用boolean值来检测back是否被点击,如果2秒后没有再次点击,它会再次变为false。
boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
//Checking for fragment count on backstack
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else if (!doubleBackToExitPressedOnce) {
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this,"Please click BACK again to exit.", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
} else {
super.onBackPressed();
return;
}
}
private boolean doubleBackToExitPressedOnce = true;
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
if (doubleBackToExitPressedOnce) {
this.doubleBackToExitPressedOnce = false;
Toast.makeText(this,"Please click BACK again to exit.", Toast.LENGTH_SHORT).show();
} else {
finish();
}
}
}
处理方式w/o:
@Override
public void onBackPressed() {
long currentMillis = System.currentTimeMillis();
if (currentMillis - this.lastPressed < 2000 && getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
// show toast if you need
}
this.lastPressed = currentMillis;
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
//if navigation drawer here navhostfragment is primary fragment
int fragments =
getSupportFragmentManager().getPrimaryNavigationFragment()
.getChildFragmentManager().getBackStackEntryCount();
if (fragments > 0) {
super.onBackPressed();
} else {
if (back_pressed + TIME_DELAY > System.currentTimeMillis()) {
super.onBackPressed();
} else {
Toast.makeText(getBaseContext(), "Press once again to exit!",
Toast.LENGTH_SHORT).show();
}
back_pressed = System.currentTimeMillis();
}
}
}
我在 SO 上关注了 this tutorial 和某些类似的答案。
我现在的onBackPressed
代码如下-
private static final int TIME_DELAY = 2000;
private static long back_pressed;
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
int fragments = getFragmentManager().getBackStackEntryCount();
if (fragments > 0) {
super.onBackPressed();
} else {
if (back_pressed + TIME_DELAY > System.currentTimeMillis()) {
super.onBackPressed();
} else {
Toast.makeText(getBaseContext(), "Press once again to exit!",
Toast.LENGTH_SHORT).show();
}
back_pressed = System.currentTimeMillis();
}
}
}
我正在像这样将片段添加到后台堆栈(在某些地方我不添加到后台堆栈)-
private void LoadSignDetailsFragment() {
Bundle args = new Bundle();
Fragment fragment = new SignDetailsFragment();
args.putBoolean("hasValues", true);
args.putBoolean("showBookmarkedSignsOnly", showBookmarkedSignsOnly);
args.putInt("sign_id", signId);
if (fragment != null) {
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragment.setArguments(args);
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit);
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
我想做的是,如果后台堆栈中有任何片段,单个 onBackPressed
迁移到前一个片段。但是,如果backstack中没有Fragment,它应该显示Toast,双击后退关闭应用程序。
我现在的代码,总是显示 Toast,并要求双回按,而不考虑后台堆栈中的 presence/absence 个片段。我想不通为什么?
以简单的方式做到这一点 使用下面的代码
Boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
System.exit(0);
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Please click BACK again to exit",
Toast.LENGTH_SHORT).show();
}
将此代码添加到您的 onCreateView 片段中
view.setOnKeyListener( new OnKeyListener()
{
private Boolean exit = false;
@Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
//logic for identifying double back press, expires after 3 seconds
if (exit) {
getActivity().finish(); // finish activity
} else {
Toast.makeText(this, "Press Back again to Exit.",
Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
exit = false;
}
}, 3 * 1000);
}
return true;
}
return false;
}
} );
或者如果你想在 activity 中添加它,你必须重写 onBackPressed 方法并添加相同的代码。
例子
private Boolean exit = false;
@Override
public void onBackPressed(){
if (exit) {
finish(); // finish activity
} else {
Toast.makeText(this, "Press Back again to Exit.",
Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
exit = false;
}
}, 3 * 1000);
}
}
但建议在 activity 中执行,而不是片段
您可以根据需要参考以下代码。如果您不使用 v4 支持片段,则必须使用 getFragmentManager()
而不是 getSupportFragmentManager()
来获取后台堆栈计数。这里我是用boolean值来检测back是否被点击,如果2秒后没有再次点击,它会再次变为false。
boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
//Checking for fragment count on backstack
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else if (!doubleBackToExitPressedOnce) {
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this,"Please click BACK again to exit.", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
} else {
super.onBackPressed();
return;
}
}
private boolean doubleBackToExitPressedOnce = true;
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
if (doubleBackToExitPressedOnce) {
this.doubleBackToExitPressedOnce = false;
Toast.makeText(this,"Please click BACK again to exit.", Toast.LENGTH_SHORT).show();
} else {
finish();
}
}
}
处理方式w/o:
@Override
public void onBackPressed() {
long currentMillis = System.currentTimeMillis();
if (currentMillis - this.lastPressed < 2000 && getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
// show toast if you need
}
this.lastPressed = currentMillis;
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
//if navigation drawer here navhostfragment is primary fragment
int fragments =
getSupportFragmentManager().getPrimaryNavigationFragment()
.getChildFragmentManager().getBackStackEntryCount();
if (fragments > 0) {
super.onBackPressed();
} else {
if (back_pressed + TIME_DELAY > System.currentTimeMillis()) {
super.onBackPressed();
} else {
Toast.makeText(getBaseContext(), "Press once again to exit!",
Toast.LENGTH_SHORT).show();
}
back_pressed = System.currentTimeMillis();
}
}
}