覆盖后退按钮以充当主页按钮


253

在按下后退按钮时,我希望我的应用程序进入停止状态,而不是进入销毁状态。

在Android 文档中,它指出:

...并非所有活动都具有按下BACK后会被销毁的行为。当用户开始在“音乐”应用程序中播放音乐,然后按BACK时,该应用程序将覆盖正常的后退行为,从而防止播放器活动被破坏,并继续播放音乐(即使其活动不再可见)

如何在自己的应用程序中复制此功能?

我认为肯定有三种可能性...

  1. 捕获后退按钮的按下(如下所示),然后调用home按钮调用的任何方法。

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
            Log.d(this.getClass().getName(), "back button pressed");
        }
        return super.onKeyDown(keyCode, event);
    }
    
  2. 捕获后退按钮按下,然后欺骗主页按钮。

  3. 捕获后退按钮的按下,然后启动主屏幕的活动,从而有效地将应用程序的活动置于停止状态。

编辑: 我知道有关服务,并且正在与此问题相关的应用程序中使用一种。该问题专门用于在按“后退”按钮时将“活动”置于停止状态而不是被破坏状态。


Answers:


338

在大多数情况下,您需要创建一个Service在后台执行某些操作,而您的可见对象Activity只需对此进行控制Service。(我敢肯定,音乐播放器以相同的方式工作,所以在文档的例子似乎有点误导。)如果是这样的话,那么你Activity可以finish像往常一样和Service仍将运行。

一种更简单的方法是捕获Back按钮按下并按如下所示调用moveTaskToBack(true)

// 2.0 and above
@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

// Before 2.0
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        moveTaskToBack(true);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

我认为首选的选择应该是活动能够正常完成,并且能够重新创建自身,例如,如果需要,可以从服务中读取当前状态。但moveTaskToBack有时也可以用作快速替代方法。

注意:如Dave所指出的,Android 2.0以下引入了一种新onBackPressed方法,以及有关如何处理“后退”按钮的这些建议


1
moveTaskToBack()似乎可以正常工作。使用此方法可能会有什么弊端?在某些情况下这可能无法按预期进行吗?
bdls 2010年

1
在更仔细地阅读其文档之后,我实际上认为它应该可以正常工作。(我最初以为它适用于该活动,但实际上它说的是“包含该活动的任务”。)但是,您当然应该自己进行测试。:)
Mirko N.

感谢Mirko,该方法似乎效果很好。如果您以后在回答该问题的人中将答案的底部更加突出,这可能会很酷-因为那是我一直在寻找的问题!
bdls 2010年

4
请阅读android-developers.blogspot.com/2009/12/…,了解处理后退键的推荐方法。
hackbod 2010年

1
@bdls从理论上讲,如果系统的资源不足,则后台活动可能会被系统杀死,因此,为了安全起见,它应该能够重新创建自己。我看了看Android音乐应用程序的源代码,没有看到任何特殊的后退按钮处理。
Mirko N.

46

使用以下代码:

public void onBackPressed() {    
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_HOME);
    startActivity(intent);
}

23

如果您想抓住Back Button,请查看Android开发者博客上的这篇文章。它涵盖了在Android 2.0中执行此操作的更简单方法,以及在1.x和2.0上运行的应用程序执行此操作的最佳方法。

但是,如果您的“活动”已停止,则仍然可能被杀死,具体取决于设备上的内存可用性。如果您希望进程在没有UI的情况下运行,则应创建一个Service该文档说明了有关服务的以下内容:

服务没有可视的用户界面,而是在后台无限期地运行。例如,一项服务可能会在用户参与其他事务时播放背景音乐,或者可能会通过网络获取数据或进行计算,然后将结果提供给需要它的活动。

这些似乎适合您的要求。



14

如果它对其他人有帮助,我有一个具有2种布局的活动,出于可视性而进行了切换,试图模拟一种page1> page2结构。如果他们在第2页上并按了“后退”按钮,我希望他们回到第1页,如果他们在第1页上按了“后退”按钮,它应该仍然可以正常工作。它很基本,但是可以用

@Override
public void onBackPressed() {
// check if page 2 is open
    RelativeLayout page2layout = (RelativeLayout)findViewById(R.id.page2layout);
    if(page2layout.getVisibility() == View.VISIBLE){
        togglePageLayout(); // my method to toggle the views
        return;
    }else{
        super.onBackPressed(); // allows standard use of backbutton for page 1
    }

}

希望它可以帮助某人,欢呼


10

工作示例

确保不要调用super.onBackPressed();

@Override
public void onBackPressed() {
   Log.d("CDA", "onBackPressed Called");
   Intent setIntent = new Intent(Intent.ACTION_MAIN);
   setIntent.addCategory(Intent.CATEGORY_HOME);
   setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   startActivity(setIntent);
}

这样,您的“后退”按钮就像“主页”按钮。它不会完成您的活动,但会将其带到后台

第二个方法是调用 moveTaskToBack(true);onBackPressed,一定要卸下super.onBackPressed


0

更好的是,OnPause()怎么样:

当活动进入后台但尚未被杀死时,被称为活动生命周期的一部分。与onResume()对应。

当活动B在活动A之前启动时,将在A上调用此回调。在A的onPause()返回之前,将不会创建B,因此请确保enter code here此处不要做任何冗长的操作。

此回调主要用于保存活动正在编辑的任何持久状态,并确保没有足够的资源来启动新活动而不会先杀死该活动,则不会丢失任何内容。

这也是执行停止动画和消耗大量CPU的其他事情的好地方,以便尽快切换到下一个活动,或者关闭诸如摄像机之类的专有资源。


0

在Android 2.0之后覆盖onBackPressed()。如

@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

0

我已经尝试了上述所有解决方案,但没有一个对我有用。当尝试以调用onCreate的方式返回MainActivity时,以下代码为我提供了帮助:

Intent.FLAG_ACTIVITY_CLEAR_TOP是关键。

  @Override
  public void onBackPressed() {
      Intent intent = new Intent(this, MainActivity.class);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
      startActivity(intent);
  }

-1

我已经使用@Mirko N.answser使用了新的Custom EditText

 public class EditViewCustom extends EditText {

    Button cancelBtn;
    RelativeLayout titleReleLayout;
    public EditViewCustom(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public EditViewCustom(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EditViewCustom(Context context) {
        super(context);
    }

    public void setViews(Button cancelBtn,RelativeLayout titleReleLayout){
        this.cancelBtn = cancelBtn;
        this.titleReleLayout = titleReleLayout;
    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            Log.d("KEYCODE_BACK","KEYCODE_BACK");
            cancelBtn.setVisibility(View.GONE);
            this.setFocusableInTouchMode(false);
            this.setFocusable(false);
            titleReleLayout.setVisibility(View.VISIBLE);

            return super.onKeyPreIme(keyCode, event);
          }

        return super.onKeyPreIme(keyCode, event);
    }

}

然后根据您的活动设置数据

 searchEditView.setViews(cancelBtn, titleRelativeLayout);

谢谢。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.