【问题标题】:Android - Overriding ActionBar back and device back buttonAndroid - 覆盖 ActionBar 后退和设备后退按钮
【发布时间】:2016-06-08 19:20:59
【问题描述】:

在我的应用中,我有一个 MainActivity 和一个 TimerActivity。 在 TimerActivity 的正常情况下,设备后退按钮和 ActionBar 的向上按钮按应有的方式工作 - 它们从 TimerActivity 引导到 MainActivity。但是当我通过单击我的应用程序的通知打开 TimerActivity 时,后退按钮会导致主屏幕而不是 MainActivity。 我希望两个后退按钮(设备和 ActionBar 的向上按钮)始终打开 MainActivity - 除非用户当然在 MainActivity 中,在这种情况下后退按钮应该关闭 MainActivity。当您通过通知打开活动时,这就是 Gmail 和 Google Drive 应用程序的工作方式,这是最有意义的。

以下是我的通知打开活动的方式:

Notification timerNotification;

mBuilder = new NotificationCompat.Builder(getApplicationContext())
    .setSmallIcon(ongoingNotificationIcon)
    .setContentTitle(ongoingNotificationContentTitle)
    .setContentText(ongoingNotificationContentText)
    .setTicker(ongoingNotificationTicker)
    .setPriority(99)
    .setOngoing(true);

Intent resultIntent = new Intent(this, TimerActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(
        this, 0, resultIntent, PendingIntent.FLAG_CANCEL_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
timerNotification = mBuilder.build();

startForeground(MyApplication.NOTIFICATION_ID, timerNotification);

我尝试像这样覆盖 TimerActivity 中的后退按钮:

public void onBackPressed() {    
    Intent intent_main = new Intent(getApplicationContext(), MainActivity.class);
    startActivity(intent_main);
}

但随后再次按下 MainActivity 上的后退按钮会将用户返回到 TimerActivity(因此用户处于循环中),而不是退出应用程序,这是所需的行为。此外,onBackPressed() 不会影响 ActionBar 的向上按钮。

【问题讨论】:

    标签: android


    【解决方案1】:
    1. 要覆盖 Actionbar Up 按钮,请使用:

      @Override
      public boolean onOptionsItemSelected(MenuItem item) 
      {
          switch(item.getItemId()) {
              case android.R.id.home:
                  //User clicked home, do whatever you want
                  return true;
              default:        
                  return super.onOptionsItemSelected(item);
          }
      }
      
    2. 要自动返回上一个活动,请在 AndroidManifest.xml 中指定上一个活动:

      <activity
          android:name=".SecondActivity"              
          android:label="@string/label_myLabel"
          android:parentActivityName=".FirstActivity">
          <meta-data
              android:name="android.support.PARENT_ACTIVITY"
              android:value="com.yourpackage.FirstActivity"/>
      </activity>
      

    【讨论】:

    • 我在清单中正确定义了父活动,但感谢主页按钮覆盖。我将 adneal 的解决方案与您的解决方案结合起来并让它发挥作用。您应该将 R.id.home 更改为 android.R.id.home
    【解决方案2】:

    onBackPressed() 不会影响 ActionBar 的向上按钮。

    “返回”按钮和“向上”按钮是两种不同的导航方式。

    From the docs:

    向上

    向上按钮用于根据 屏幕之间的层次关系。

    返回

    系统后退按钮用于导航,按时间倒序排列 顺序,通过用户最近工作过的屏幕历史 和。一般是根据时间关系 屏幕,而不是应用的层次结构。

    因此,您所描述的问题实际上是 推荐 浏览您的应用的方式。

    尽管如此,如果您希望用户在按下 Notification 后从您的 TimerActivity 转到您的 MainActivity,最简单的实现方法是包含一个 Intent 额外以检查您何时从您的Notification 启动Activity

    这是一个例子:

    Intent resultIntent = new Intent(this, TimerActivity.class);
    resultIntent.putExtra("fromNotification", true);
    

    在你的TimerActivity

    private boolean mFromNotification;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        final Bundle args = getIntent().getExtras();
        if (args != null) {
            mFromNotification = args.getBoolean("fromNotification");
        }
    }
    
    @Override
    public void onBackPressed() {
        if (mFromNotification) {
            startActivity(new Intent(this, MainActivity.class));
            finish();
        } else {
            super.onBackPressed();
        }
    }
    

    【讨论】:

    • TaskStackBuilder 为您完成所有后退按钮堆栈的构建 - 您无需自己处理。
    • 这解决了后退按钮的问题,但ActionBar的向上按钮仍然关闭应用程序而不是返回到MainActivity,即使我已经将.MainActivity定义为Manifest中的父Activity。至于推荐的行为,如果 Gmail 和 Google Drive 不遵循,我想我也不必这样做。
    • 我也对向上按钮做了你所说的做后退按钮并得到了一个可行的解决方案。 TaskStackBuilder 太复杂了,我现在无法理解。
    【解决方案3】:

    正如Notifications Setting up a regular activity PendingIntent 中所解释的,您应该使用TaskStackBuilder 来构建一个合成后退堆栈,以便您的后退按钮的功能就像用户导航到他们的正常位置一样:

    ...
    Intent resultIntent = new Intent(this, ResultActivity.class);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    // Adds the back stack
    stackBuilder.addParentStack(ResultActivity.class);
    // Adds the Intent to the top of the stack
    stackBuilder.addNextIntent(resultIntent);
    // Gets a PendingIntent containing the entire back stack
    PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    ...
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    builder.setContentIntent(resultPendingIntent);
    NotificationManager mNotificationManager =
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.notify(id, builder.build());
    

    正如您所注意到的,Action Bar Up 操作与您是否来自通知没有区别(如果您设置正确,则与预期一样)。

    【讨论】:

    • Action Bar Up 操作也无法正常工作(至少在 Gmail 和 Google Drive 中,它总是会导致父活动,而不是像我的情况那样关闭应用程序)
    • @TimSim - 那么您需要按照该链接中关于如何设置“向上”按钮的其余说明进行操作。
    • 但是我已经将 .MainActivity 定义为 Manifest 中 TimerActivity 的父活动,并且它可以正常工作,除非从通知中打开活动。