Botões de ação de notificação dinâmica no Xamarin.iOS

No iOS 12, as notificações podem adicionar, remover e atualizar dinamicamente os botões de ação associados. Essa personalização possibilita fornecer aos usuários ações diretamente relevantes para o conteúdo da notificação e a interação do usuário com ela.

Aplicativo de exemplo: RedGreenNotifications

Os trechos de código neste guia vêm de um aplicativo de exemplo, que demonstra como usar o Xamarin.iOS para trabalhar com botões de ação de notificação no iOS 12.

Este aplicativo de exemplo envia dois tipos de notificações locais: vermelho e verde. Depois de fazer com que o aplicativo envie uma notificação, use o 3D Touch para exibir sua interface de usuário personalizada. Em seguida, use os botões de ação da notificação para girar a imagem exibida. À medida que a imagem gira, um botão Redefinir rotação aparece e desaparece conforme necessário.

Trechos de código neste guia vêm deste aplicativo de exemplo.

Botões de ação padrão

A categoria de uma notificação determina seus botões de ação padrão.

Crie e registre categorias de notificação enquanto um aplicativo é iniciado. Por exemplo, no aplicativo de exemplo, o FinishedLaunching método de AppDelegate faz o seguinte:

  • Define uma categoria para notificações vermelhas e outra para notificações verdes
  • Registra essas categorias chamando o SetNotificationCategories método de UNUserNotificationCenter
  • Anexa um único UNNotificationAction para cada categoria

O código de exemplo a seguir mostra como isso funciona:

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);
    });
    // ...
}

Com base neste código, qualquer notificação cujo Content.CategoryIdentifier é "categoria vermelha" ou "categoria verde" irá, por padrão, mostrar um botão de ação Girar 20° .

Manipulação no aplicativo de botões de ação de notificação

UNUserNotificationCenter tem uma Delegate propriedade do tipo IUNUserNotificationCenterDelegate.

No aplicativo de exemplo, AppDelegate define-se como o representante da central de notificações do usuário em 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;
        // ...

Em seguida, AppDelegate implementa DidReceiveNotificationResponse Para manipular os toques no botão de ação:

[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();
        }

Essa implementação de DidReceiveNotificationResponse não manipula o botão de ação Girar 20° da notificação. Em vez disso, a extensão de conteúdo da notificação lida com toques nesse botão. A próxima seção discute mais detalhadamente o manuseio do botão de ação de notificação.

Botões de ação na extensão de conteúdo de notificação

Uma extensão de conteúdo de notificação contém um controlador de exibição que define a interface personalizada para uma notificação.

Este controlador de exibição pode usar os GetNotificationActions métodos e SetNotificationActions em seu ExtensionContext para acessar e modificar os botões de ação da notificação.

No aplicativo de exemplo, o controlador de exibição da extensão de conteúdo de notificação modifica os botões de ação somente ao responder a um toque em um botão de ação já existente.

Observação

Uma extensão de conteúdo de notificação pode responder a um toque de botão de ação no método do DidReceiveNotificationResponse controlador de exibição, declarado como parte de IUNNotificationContentExtension.

Embora compartilhe um nome com o DidReceiveNotificationResponse método descrito acima, este é um método diferente.

Depois que uma extensão de conteúdo de notificação terminar de processar um toque de botão, ela poderá escolher se deseja ou não dizer ao aplicativo principal para lidar com esse mesmo toque de botão. Para fazer isso, ele deve passar um valor apropriado de UNNotificationContentExtensionResponseOption para seu manipulador de conclusão:

  • Dismiss indica que a interface de notificação deve ser descartada e que o aplicativo principal não precisa manipular o toque no botão.
  • DismissAndForwardAction indica que a interface de notificação deve ser descartada e que o aplicativo principal também deve lidar com o toque no botão.
  • DoNotDismiss indica que a interface de notificação não deve ser descartada e que o aplicativo principal não precisa manipular o toque no botão.

O método da extensão de DidReceiveNotificationResponse conteúdo determina qual botão de ação foi tocado, gira a imagem na interface da notificação e mostra ou oculta um botão de ação Redefinir :

[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);
}

Nesse caso, o método passa UNNotificationContentExtensionResponseOption.DoNotDismiss para seu manipulador de conclusão. Isso significa que a interface da notificação permanecerá aberta.