Android 的 synthetic back stack 是好設計嗎?

在Android 4.0之前,如果在app A中點擊通知進入app B,按返回鍵會回到app A。這比較符合通知的使用場景:處理任務 - 中斷當前任務處理通知 - 繼續處理當前任務。

而Android 4.1引入了synthetic back stack。從這個版本開始,點擊通知進入Google的 app(及其它使用了該API的app),按返回鍵會在app B內向上導航,最終回到桌面。如果想直接回到app A,必須通過多任務按鈕。

Android 4.1 APIs

Note: When the user enters a deep activity in your app and it creates a new task for your app, the system actually inserts the stack of parent activities into the task. As such, pressing the Back button also navigates back through the stack of parent activities.

Navigation with Back and Up

Navigation into Your App via Home Screen Widgets and Notifications

You can use Home screen widgets or notifications to help your users navigate directly to screens deep within your apps hierarchy. For example, Gmails Inbox widget and new message notification can both bypass the Inbox screen, taking the user directly to a conversation view.

For both of these cases, handle the Up button as follows:

  • If the destination screen is typically reached from one particular screen within your app, Up should navigate to that screen.
  • Otherwise, Up should navigate to the topmost ("Home") screen of your app.

In the case of the Back button, you should make navigation more predictable by inserting into the tasks back stack the complete upward navigation path to the apps topmost screen. This allows users whove forgotten how they entered your app to navigate to the apps topmost screen before exiting.

As an example, Gmails Home screen widget has a button for diving directly to its compose screen. Up or Back from the compose screen would take the user to the Inbox, and from there the Back button continues to Home.

我對這個設計的問題是:

1. 相對於前述使用場景,「處理通知時需要轉到app B的上級頁面」頻率較低,為什麼要為它而使常見場景的操作變繁瑣?

2. 既然"up"和"back"導航可以不一致,是否可以讓"up"負責轉到上級頁面,而保持"back"回到被通知打斷的app這一行為?


你想按照你的場景來實現,連多餘的代碼都不用加。反而遵循google的設計要多寫代碼好嘛。

我不想討論實際情況哪個場景是更有效的,只想說這是怎麼實現的。你可以根據自己理解實現任意一種場景就好了。

註:以下英文內容全部來自谷歌官方文檔。

In almost all situations, the system maintains a back stack of activities while the user navigates your application. This allows the system to properly navigate backward when the user presses the Back button. However, there are a few cases in which your app should manually specify the Back behavior in order to provide the best user experience.

Navigation patterns that require you to manually specify the Back behavior include:

  • When the user enters a deep-level activity directly from a notification, an app widget, or the navigation drawer.
  • Certain cases in which the user navigates between fragments.
  • When the user navigates web pages in a WebView.

大部分情況下,系統會默認維護自己的stack。所以正常情況點擊back是回到上一個操作歷史的。但是谷歌認為有幾個特殊的case不能使用默認的歷史,而你說的從widget,通知或者另一個應用啟動這些情況就是特殊的case。

為了實現這種目標,需要多加幾個步驟:

1.Specify parent activities in the manifest

Beginning in Android 4.1 (API level 16), you can declare the logical parent of each activity by specifying the android:parentActivityName attribute in the & element. This allows the system to facilitate navigation patterns because it can determine the logical Back or Up navigation path with this information.

If your app supports Android 4.0 and lower, include the Support Library with your app and add a &element inside the &. Then specify the parent activity as the value for android.support.PARENT_ACTIVITY, matching the android:parentActivityName attribute.

第一步需要給每一個activity指定邏輯上的parentActivity。

&
...
&
&
...
&
&
&
&
&
&
&

上邊是示例代碼。

2.Create back stack when starting the activity

Adding activities to the back stack begins upon the event that takes the user into your app. That is, instead of calling startActivity(), use the TaskStackBuilder APIs to define each activity that should be placed into a new back stack. Then begin the target activity by calling startActivities(), or create the appropriate PendingIntent by calling getPendingIntent().

For example, when a notification takes the user to an activity deep in your app hierarchy, you can use this code to create a PendingIntent that starts an activity and inserts a new back stack into the target task:

第二步是在由外部應用starrtActivity的時候,需要新建一個stack,把這個activity放在一個新的stack中。這樣再點擊back時候,就不會返回到歷史上的上一個界面了,而是跳轉到邏輯上的parentActivity。

// Intent for the activity to open when user selects the notification
Intent detailsIntent = new Intent(this, DetailsActivity.class);

// Use TaskStackBuilder to build the back stack and get the PendingIntent
PendingIntent pendingIntent =
TaskStackBuilder.create(this)
// add all of DetailsActivitys parents to the stack,
// followed by DetailsActivity itself
.addNextIntentWithParentStack(upIntent)
.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(pendingIntent);

上邊是示例代碼。

所以想要實現這種back不回到啟動的A應用,而是跳到B應用的parentActicity時候,是需要多加不少工作的。如果題主覺得你的場景有道理,那就更省事了,都不用加代碼了是不是。


好像並沒有直接回答題主的問題,加上題主修改了題目,從個人角度補充一點內容吧:

從設計的角度,嚴格上來講不是好的設計,增加一種行為必然會增加用戶的認知負擔,但是個人認為實際使用中是存在UP跟Back兩種需求,Android嘗試提供一種方式去解決,解決方式有待提高。

既成事實角度來講,這兩種行為確實也帶來了一些用戶的困惑,這裡也有一部分原因是Android 4.0之前沒有去區分,用戶已經習慣了只有「Back」的一種行為。

---原答案---

Android官方其實定義的很清楚了,開發者沒有認真細緻執行罷了吧。

印象中從4.0開始,Android定義有2個back行為:

1. 界面左上角的hierarchical back:點擊會返回至當前應用的上一層級。

2. Hard key中的historical back:點擊回到上一個界面。

一個是UI層級的返回,一個是操作歷史的返回,還是比較容易區分的。

按照官方的設定,如果用戶在同一個應用內導航,無論點哪個back,返回的結果是一致的,但是如果是在應用間跳轉,那麼返回的結果就不同了。

很多第三方應用開發者沒有關注這2個的區別,才造成目前依然可以看見的混亂。


推薦閱讀:

iuni為什麼不掛金立的牌子,金立以後會用iuni么?
那些對Android進行所謂「定製」的手機廠商是否會全面採用Android L?
為什麼有些網站在chrome上能夠讓狀態欄變色而絕大部分網站不可以?
現在哪些手機廠商操作系統還有二級菜單(應用抽屜)?
如何看待 Android O 的 Adaptive icons?

TAG:用戶界面設計 | Android | AndroidUI |