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