Android - 如何覆盖“后退”按钮,使其不会完成()我的活动?

Posted

技术标签:

【中文标题】Android - 如何覆盖“后退”按钮,使其不会完成()我的活动?【英文标题】:Android - How To Override the "Back" button so it doesn't Finish() my Activity? 【发布时间】:2011-03-09 16:36:27 【问题描述】:

我目前有一个 Activity,当它显示时,通知也会显示在通知栏中。

这样当用户按下 home 键并将 Activity 推送到后台时,他们可以通过 Notification 回到 Activity。

当用户按下后退按钮时会出现问题,我的 Activity 被破坏但通知仍然存在,因为我希望用户能够按下后退但仍然能够通过通知进入 Activity。但是当一个用户尝试这个时,我得到空指针,因为它试图开始一个新的活动,而不是带回旧的活动。

所以基本上我希望后退按钮与主页按钮完全相同,这是我迄今为止尝试过的方式:


        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event)  
            if (Integer.parseInt(android.os.Build.VERSION.SDK) < 5
                    && keyCode == KeyEvent.KEYCODE_BACK
                    && event.getRepeatCount() == 0) 
                Log.d("CDA", "onKeyDown Called");
                onBackPressed();
            

            return super.onKeyDown(keyCode, event);
        

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

            return;
           

但是上面的代码似乎仍然允许我的 Activity 被销毁,当按下后退按钮时,如何阻止我的 Activity 被销毁?

【问题讨论】:

有一个类似的问题:***.com/questions/2459848/… 类似的答案.. ***.com/questions/5914040/… 另外我认为你必须将代码更改为` if (Integer.parseInt(android.os.Build.VERSION.SDK) > 5, the >。 即使你解决了这个问题,你仍然必须处理系统杀死你的应用程序的可能性,对吧?我的意思是,null 情况仍然可能吗?或者如果系统出于任何原因终止了您的应用程序,这是否也会删除您的通知?我认为这一定是个问题,因为即使应用程序不存在,通知的目的也是存在的。 developer.android.com/guide/navigation/navigation-custom-back 【参考方案1】:

删除您的关键侦听器或在您拥有KEY_BACK 时返回true

您只需要以下内容来捕捉返回键(确保不要在onBackPressed() 中调用super)。

另外,如果您打算让服务在后台运行,请务必查看 startForeground() 并确保有持续的通知,否则 Android 会在需要释放内存时终止您的服务。

@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);

【讨论】:

【参考方案2】:

只用一行代码就更容易实现了:

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

【讨论】:

这应该是公认的答案。这正是问题所要求的,并且正在使用干净的内置功能。 谢谢 :) 你能详细说明它背后的概念吗? 您只需覆盖 onBackPressed() 事件,使其将活动移到后面。 当您从主屏幕重新启动应用程序时(如果任务堆栈上有另一个活动),此解决方案不会恢复活动。【参考方案3】:

只需这样做..

@Override
public void onBackPressed() 
    //super.onBackPressed();

注释掉 //super.onBackPressed();会成功的

【讨论】:

一个有用的观察,但这不会导致后退按钮什么都不做,就好像它坏了一样?这不是一件好事——让用户感到困惑和烦恼。恕我直言,必须从另一个答案中添加逻辑,以像所要求的那样充当主页按钮。接受的答案提到他们故意不调用超级方法。 是的,你完全正确。它只会覆盖后退按钮,并且在您将一些逻辑放在那里之前什么都不做。可能是双击按钮关闭应用程序的条件,或者您只想禁用正在进行的操作(进度对话框)等,但它完全符合要求。【参考方案4】:

我认为您想要的不是覆盖后退按钮(这似乎不是一个好主意 - Android 操作系统定义了该行为,为什么要更改它?),而是使用 Activity Lifecycle 并保留您的设置/data 在onSaveInstanceState(Bundle) 事件中。

@Override
onSaveInstanceState(Bundle frozenState) 
    frozenState.putSerializable("object_key",
        someSerializableClassYouWantToPersist);
    // etc. until you have everything important stored in the bundle

然后您使用onCreate(Bundle) 将所有内容从该持久包中取出并重新创建您的状态。

@Override
onCreate(Bundle savedInstanceState) 
    if(savedInstanceState!=null) //It could be null if starting the app.
        mCustomObject = savedInstanceState.getSerializable("object_key");
    
    // etc. until you have reloaded everything you stored

考虑一下上面的伪代码,为您指明正确的方向。阅读Activity Lifecycle 应该可以帮助您确定完成您正在寻找的最佳方法。

【讨论】:

嗨 Kiswa,这是真的,我不想更改默认行为。我已经尝试使用 onSavedInstanceState 并且它不起作用,但我相信我现在已经发现了我的错误。谢谢 我遇到过至少一些我想模拟标准 Activity 堆栈行为而不实际启动新 Activity 的情况。在这些情况下,我认为覆盖默认的 onBackPressed() 行为是合适的。不过,总的来说,我同意:避免覆盖。 我同意@Matt。我目前正在开发一个使用 NDK 的跨平台游戏。因此,如果一切都是一个单一的活动,那是最简单的。因此,返回按钮的默认行为是退出应用程序,这不是大多数用户所期望的。所以我不得不覆盖默认行为以使活动表现不同,就好像用户实际上去了不同的活动,并且只在某些情况下退出应用程序。 onSaveInstanceState 和保存数据不是完全不同的问题吗? @Ted - 如果您说除了 onSaveInstanceState 之外,还需要保留非 UI 应用程序数据的代码,那么我同意。一旦您放弃前台,您的应用程序可能会在没有进一步警告的情况下被终止。必须始终保存任何重要的东西。另一方面,我认为应用程序生命周期方法将被调用,无论您使用什么技术来隐藏应用程序但保留它,因此不需要仅为这种情况添加保存逻辑。无论如何,您的应用都需要在所有正确的地方使用该代码。【参考方案5】:

试试这个:

@Override
public void onBackPressed() 
    finish();

【讨论】:

【参考方案6】:

如果您想处理后退按钮(在手机底部)和主页按钮(操作栏左侧)的行为,我在项目中使用的这个自定义活动可以帮到你。

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;

/**
 * Activity where the home action bar button behaves like back by default
 */
public class BackActivity extends AppCompatActivity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setupHomeButton();
    

    private void setupHomeButton() 
        final ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) 
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeButtonEnabled(true);
        
    

    @Override
    public boolean onOptionsItemSelected(MenuItem item) 
        switch (item.getItemId()) 
            case android.R.id.home:
                onMenuHomePressed();
                return true;
        
        return super.onOptionsItemSelected(item);
    

    protected void onMenuHomePressed() 
        onBackPressed();
    

在您的活动中的使用示例:

public class SomeActivity extends BackActivity 

    // ....

    @Override
    public void onBackPressed()
    
        // Example of logic
        if ( yourConditionToOverride ) 
            // ... do your logic ...
         else 
            super.onBackPressed();
        
        

【讨论】:

【参考方案7】:
@Override
public void onBackPressed() 
// Put your code here.


//I had to go back to the dashboard. Hence,

@Override
public void onBackPressed() 
    Intent intent = new Intent(this,Dashboard.class);
    startActivity(intent);

Just write this above or below the onCreate Method(within the class)

【讨论】:

【参考方案8】:

在 Kotlin 中:

val callback = requireActivity().onBackPressedDispatcher.addCallback(this) 
    // Handle the back button event

更多信息您可以查看this。

还有专门的 question 关于在 Kotlin 中覆盖后退按钮。

【讨论】:

【参考方案9】:

看起来我很晚了,但对于那些需要切换到新屏幕并清除后退按钮堆栈的人来说,这里是一个非常简单的解决方案。

startActivity(new Intent(this,your-new-screen.class));
finishAffinity();

finishAffinity();方法清除返回按钮堆栈。

【讨论】:

【参考方案10】:

就这样做

@Override
public void onBackPressed() 
    super.onBackPressed();

【讨论】:

这将退出或从应用程序转到上一个屏幕,而不是返回主页

以上是关于Android - 如何覆盖“后退”按钮,使其不会完成()我的活动?的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖android中的操作栏后退按钮?

按下后退按钮时未调用Android onUserLeaveHint()

覆盖Android中顶部菜单问题的后退按钮事件

Cordova 后退按钮覆盖默认行为

如何自定义ActionBar上的后退按钮

覆盖后退按钮 wix 反应原生导航 V2?