UWP - 處理 back-navigation event 機制
過去開發 UAP 的時候對於用戶按下 Back 鍵,App 會被觸發 Frame.GoBack() 與 Page.OnNavigatedFrom(),
在 App 處理 Phone 的時候會有這樣的代碼:(至於 Windows RT App,則是在畫面上加入一個 Back 鈕提供 Back 任務)
1: Windows.Phone.UI.Input.HardwareButtons.BackPressed += HardwareButtons_BackPressed;
2:
3: /// <summary>
4: /// Invoked when the hardware back button is pressed. For Windows Phone only.
5: /// </summary>
6: /// <param name="sender">Instance that triggered the event.</param>
7: /// <param name="e">Event data describing the conditions that led to the event.</param>
8: private void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
9: {
10: // do something and go bak
11: if (Window.Current.Content.GetType() == typeof(Frame))
12: {
13: Frame rootFrame = Window.Current.Content as Frame;
14: rootFrame.GoBack();
15: }}
16: }
到了 UWP 開發時,需要自己按照 App 預計支援的 device families 來處理這個 Back 事件,那如果沒有 Back 實體按鍵要怎麽處理?
針對這兩個問題分別説明:
1. 使用 Adaptive code 來判別 Mobile 設備是否支援 Back 實體按鈕:
1: protected override void OnLaunched(LaunchActivatedEventArgs e)
2: {
3: // 利用 ApiInformation.IsTypePresent 判斷是否支援 Back 實體按鍵
4: bool isHardwareButtonsAPIPresent =
5: Windows.Foundation.Metadata.ApiInformation.IsTypePresent(
6: "Windows.Phone.UI.Input.HardwareButtons");
7:
8: // 如果有加以注冊 HardwareButtons.CameraPressed
9: // 要記得先加入 Windows Mobile Extensions for the UWP
10: if (isHardwareButtonsAPIPresent)
11: {
12: Windows.Phone.UI.Input.HardwareButtons.BackPressed
13: += HardwareButtons_BackPressed;
14: }
15: }
用來檢查要使用的 member, type, 或是 API 是否被支援,讓你能安全 API 呼叫跨多種設備。幾個常用的 Methods:
Method | Description |
IsTypePresent | Returns true or false to indicate whether a specified type is present. |
IsApiContractPresent(String,UInt16) | Returns true or false to indicate whether the API contract with the specified name and major version number is present. |
IsEventPresent | Returns true or false to indicate whether a specified event is present for a specified type. |
IsMethodPresent(String,String) | Returns true or false to indicate whether a specified method is present for a specified type. |
IsMethodPresent(String,String,UInt32) | Returns true or false to indicate whether a specified method overload with the specified number of input parameters is present for a specified type. |
針對 Phone 主要有幾種實體按鍵事件可以處理:
Event | Description |
BackPressed | Occurs when the user presses the hardware Back button. |
CameraHalfPressed | Occurs when the user presses the hardware camera button halfway. |
CameraPressed | Occurs when the user presses the hardware camera button. |
CameraReleased | Occurs when the user releases the hardware camera button. |
2. 使用 SystemNavigationManager 在 App.xaml.cs 時取得 CurrentView 并且注冊 BackRequest 事件:
2-1. 在 OnLaunched 加入對 rootFrame.Navigated 事件的注冊與加入 SystemNavigationManager 注冊 BackReqeust 事件:
1: protected override void OnLaunched(LaunchActivatedEventArgs e)
2: {
3: Frame rootFrame = Window.Current.Content as Frame;
4:
5: // Do not repeat app initialization when the Window already has content,
6: // just ensure that the window is active
7: if (rootFrame == null)
8: {
9: // Create a Frame to act as the navigation context and navigate to the first page
10: rootFrame = new Frame();
11:
12: rootFrame.NavigationFailed += OnNavigationFailed;
13: // 加入該事件,用來判讀是否要顯示 Back 按鈕
14: rootFrame.Navigated += RootFrame_Navigated;
15:
16: if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
17: {
18: //TODO: Load state from previously suspended application
19: }
20:
21: // Place the frame in the current Window
22: Window.Current.Content = rootFrame;
23: }
24:
25: if (rootFrame.Content == null)
26: {
27: // When the navigation stack isn't restored navigate to the first page,
28: // configuring the new page by passing required information as a navigation
29: // parameter
30: rootFrame.Navigate(typeof(MainPage), e.Arguments);
31: }
32: // Ensure the current window is active
33: Window.Current.Activate();
34:
35: // 宣告要處理 Back 事件
36: SystemNavigationManager.GetForCurrentView().BackRequested += App_BackRequested;
37: }
2-2. 處理 BackRequest 事件:
1:
2: private void App_BackRequested(object sender, BackRequestedEventArgs e)
3: {
4: Frame rootFrame = Window.Current.Content as Frame;
5: if (rootFrame.CanGoBack)
6: {
7: e.Handled = true;
8: rootFrame.GoBack();
9: }
10: }
2-3. 處理在 rootFrame.Navigated 時判斷是否要顯示 Back 按鈕:
1:
2: private void RootFrame_Navigated(object sender, NavigationEventArgs e)
3: {
4: // Each time a navigation event occurs, update the Back button's visibility
5: SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
6: ((Frame)sender).CanGoBack ?
7: AppViewBackButtonVisibility.Visible :
8: AppViewBackButtonVisibility.Collapsed;
9: }
提供方法回應系統發出的 back-navigation events。讓開發人員可以處理:
- user 按下 hardware button 或是系統提供的 back button
- gestures 造成的 back
- voice commands 觸發的 back
主要元素如下:
Type | Name | Description |
Event | BackRequested | Occurs when the user invokes the system provided button, gesture, or voice command for back-navigation. |
Method | GetForCurrentView | Returns the SystemNavigationManager object associated with the current window. |
Property | AppViewBackButtonVisibility | Read/write,Gets or sets a value that indicates whether a back button is shown in the system UI. 如果以 Win10 系統來看, back button 就是出現在 App 視窗左上角。 |
根據<Handling the Back Button in Windows 10 UWP Apps>的説明,Windows.UI.Core.SystemNavigationManager 有兩個重要的任務:
- 提供給 App 運行在沒有實體 Back 按鍵上時,可以提供畫面出現一個 digital back button 讓用戶可以返回上一個畫面;
- 允許 App 去注冊處理 Back 按鈕(software or hardware)的 click 事件,不需要爲了單純處理 Back 按鈕而加入真個 extension SDKs;
[注意]
- 同時注冊了 Windows.Phone.UI.Input.HardwareButtons.BackPressed 與 SystemNavigationManager.GetForCurrentView().BackRequested,
會先觸發 HardwareButtons 的事件才會輪到 BackRequested,如果 HardwareButtons 加了 e.Handled = true; 那麽 BackRequested 就不會收到。 - BackRequested 衹有允許 foreground app 收到事件。
- If the device doesn't provide any back-navigation button, gesture, or command, the event is not raised.
======
這篇單純筆記,因爲很容易忘記要做 Back 鍵的處理,然後再去找到對應的 Namespace 來判斷,所以特別記錄該篇方便查詢。
References:
〉Handling the Back Button in Windows 10 UWP Apps
〉API Convergence Gets Real in Windows 10
〉Developing Universal Windows Apps with C# and XAML
〉Navigation design basics for Universal Windows Platform (UWP) apps (重要)
〉Guidelines for back buttons (重要)
〉Navigation (重要)
〉Universal Windows Apps with XAML and C# Unleashed: Threading, Windows, and Pages
〉Get Ready for Windows 10: Learning Universal Windows App Development
〉Developing Universal Windows Apps with C# and XAML