共用方式為


Xamarin.iOS 中的動態通知動作按鈕

在 iOS 12 中,通知可以動態新增、移除及更新其相關聯的動作按鈕。 這類自定義可讓您為使用者提供與通知內容和使用者與其互動直接相關的動作。

範例應用程式:RedGreenNotifications

本指南中的代碼段來自範例應用程式,示範如何使用 Xamarin.iOS 來處理 iOS 12 中的通知動作按鈕。

此範例應用程式會傳送兩種類型的本機通知:紅色和綠色。 讓應用程式傳送通知之後,請使用 3D Touch 來檢視其自定義使用者介面。 然後,使用通知的動作按鈕來旋轉它所顯示的影像。 當影像旋轉時,[ 重設旋轉 ] 按鈕隨即出現,並視需要消失。

本指南中的代碼段來自此範例應用程式。

默認動作按鈕

通知的類別會決定其預設動作按鈕。

在應用程式啟動時建立和註冊通知類別。 例如,在 範例應用程式中FinishedLaunchingAppDelegate 方法會執行下列動作:

下列範例程式代碼示範其運作方式:

public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
    // Request authorization to send notifications
    UNUserNotificationCenter center = UNUserNotificationCenter.Current;
    var options = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Sound | UNAuthorizationOptions.Provisional | UNAuthorizationOptions.ProvidesAppNotificationSettings;
    center.RequestAuthorization(options, (bool success, NSError error) =>
    {
        // ...
        var rotateTwentyDegreesAction = UNNotificationAction.FromIdentifier("rotate-twenty-degrees-action", "Rotate 20°", UNNotificationActionOptions.None);

        var redCategory = UNNotificationCategory.FromIdentifier(
            "red-category",
            new UNNotificationAction[] { rotateTwentyDegreesAction },
            new string[] { },
            UNNotificationCategoryOptions.CustomDismissAction
        );

        var greenCategory = UNNotificationCategory.FromIdentifier(
            "green-category",
            new UNNotificationAction[] { rotateTwentyDegreesAction },
            new string[] { },
            UNNotificationCategoryOptions.CustomDismissAction
        );

        var set = new NSSet<UNNotificationCategory>(redCategory, greenCategory);
        center.SetNotificationCategories(set);
    });
    // ...
}

根據此程序代碼,其任何通知 Content.CategoryIdentifier 是 “red-category” 或 “green-category” 預設 會顯示 [旋轉 20° 動作] 按鈕。

通知動作按鈕的應用程式內處理

UNUserNotificationCenterDelegate具有類型的IUNUserNotificationCenterDelegate屬性。

在範例應用程式中, AppDelegate 將本身設定為 中的 FinishedLaunching使用者通知中心委派:

public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
    // Request authorization to send notifications
    UNUserNotificationCenter center = UNUserNotificationCenter.Current;
    var options = // ...
    center.RequestAuthorization(options, (bool success, NSError error) =>
    {
        center.Delegate = this;
        // ...

然後, AppDelegate 實作 DidReceiveNotificationResponse 處理動作按鈕點選:

[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, System.Action completionHandler)
{
    if (response.IsDefaultAction)
    {
        Console.WriteLine("ACTION: Default");
    }
    if (response.IsDismissAction)
    {
        Console.WriteLine("ACTION: Dismiss");
    }
    else
    {
        Console.WriteLine($"ACTION: {response.ActionIdentifier}");
    }

    completionHandler();
        }

的這個實 DidReceiveNotificationResponse 作不會處理通知的 [旋轉 20° 動作] 按鈕。 相反地,通知的內容延伸模組會處理此按鈕的點選。 下一節會進一步討論通知動作按鈕處理。

通知內容延伸模組中的動作按鈕

通知內容延伸模組包含定義通知自定義介面的檢視控制器。

此檢視控制器可以在 GetNotificationActions 其上使用 和 SetNotificationActions 方法 ExtensionContext 屬性可存取和修改通知的動作按鈕。

在範例應用程式中,通知內容延伸模組的檢視控制器只有在回應已存在的動作按鈕時,才會修改動作按鈕。

注意

通知內容延伸模組可以響應檢視控制器DidReceiveNotificationResponse方法中的動作按鈕點選,宣告為IUNNotificationContentExtension一部分。

雖然它與DidReceiveNotificationResponse上述方法共享名稱,但這是不同的方法。

通知內容延伸模組完成處理按鈕點選之後,可以選擇是否要告訴主要應用程式處理相同的按鈕點選。 若要這樣做,它必須將適當的 UNNotificationContentExtensionResponseOption傳遞給其完成處理程式:

  • Dismiss 表示應該關閉通知介面,而且主要應用程式不需要處理按鈕點選。
  • DismissAndForwardAction 表示應該關閉通知介面,而且主要應用程式也應該處理按鈕點選。
  • DoNotDismiss 表示不應該關閉通知介面,而且主要應用程式不需要處理按鈕點選。

內容延伸模組 DidReceiveNotificationResponse 的 方法會決定點選的動作按鈕、旋轉通知介面中的影像,以及顯示或隱藏 [ 重設 動作] 按鈕:

[Export("didReceiveNotificationResponse:completionHandler:")]
public void DidReceiveNotificationResponse(UNNotificationResponse response, Action<UNNotificationContentExtensionResponseOption> completionHandler)
{
    var rotationAction = ExtensionContext.GetNotificationActions()[0];

    if (response.ActionIdentifier == "rotate-twenty-degrees-action")
    {
        rotationButtonTaps += 1;

        double radians = (20 * rotationButtonTaps) * (2 * Math.PI / 360.0);
        Xamagon.Transform = CGAffineTransform.MakeRotation((float)radians);

        // 9 rotations * 20 degrees = 180 degrees. No reason to
        // show the reset rotation button when the image is half
        // or fully rotated.
        if (rotationButtonTaps % 9 == 0)
        {
            ExtensionContext.SetNotificationActions(new UNNotificationAction[] { rotationAction });
        }
        else if (rotationButtonTaps % 9 == 1)
        {
            var resetRotationAction = UNNotificationAction.FromIdentifier("reset-rotation-action", "Reset rotation", UNNotificationActionOptions.None);
            ExtensionContext.SetNotificationActions(new UNNotificationAction[] { rotationAction, resetRotationAction });
        }
    }

    if (response.ActionIdentifier == "reset-rotation-action")
    {
        rotationButtonTaps = 0;

        double radians = (20 * rotationButtonTaps) * (2 * Math.PI / 360.0);
        Xamagon.Transform = CGAffineTransform.MakeRotation((float)radians);

        ExtensionContext.SetNotificationActions(new UNNotificationAction[] { rotationAction });
    }

    completionHandler(UNNotificationContentExtensionResponseOption.DoNotDismiss);
}

在此情況下,方法會傳遞 UNNotificationContentExtensionResponseOption.DoNotDismiss 至其完成處理程式。 這表示通知的介面會保持開啟狀態。