Кнопки действия динамического уведомления в Xamarin.iOS

В iOS 12 уведомления могут динамически добавлять, удалять и обновлять связанные с ними кнопки действий. Такая настройка позволяет предоставить пользователям действия, непосредственно относящиеся к содержимому уведомления и взаимодействию пользователя с ним.

Пример приложения: RedGreenNotifications

Фрагменты кода в этом руководстве получены из примера приложения RedGreenNotifications , в котором показано, как использовать Xamarin.iOS для работы с кнопками действий уведомлений в iOS 12.

В этом примере приложения отправляются два типа локальных уведомлений: красный и зеленый. После отправки уведомления используйте 3D Touch для просмотра пользовательского пользовательского интерфейса. Затем используйте кнопки действий уведомления для поворота отображаемого изображения. По мере поворота изображения появится кнопка "Сброс поворота " и исчезает по мере необходимости.

Фрагменты кода в этом руководстве поступают из этого примера приложения.

Кнопки действий по умолчанию

Категория уведомления определяет кнопки действий по умолчанию.

Создание и регистрация категорий уведомлений во время запуска приложения. Например, в примере приложенияFinishedLaunching метод AppDelegate выполняет следующее:

  • Определяет одну категорию красных уведомлений и другую для зеленых уведомлений
  • Регистрирует эти категории путем вызова SetNotificationCategories метод UNUserNotificationCenter
  • Присоединение одного UNNotificationAction для каждой категории

В следующем примере кода показано, как это работает:

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Имеет значение "красная категория" или "зеленая категория", по умолчанию отображается кнопка "Повернуть 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 обработчику завершения. Это означает, что интерфейс уведомления останется открытым.