Introducción a 3D Touch en Xamarin.iOS

En este artículo se explica el uso de los nuevos gestos de iPhone 6s y iPhone 6s Plus 3D Touch en la aplicación.

Ejemplos de aplicaciones habilitadas 3D Touch

En este artículo se proporcionará e introducción al uso de las nuevas API 3D Touch para agregar gestos sensibles a la presión a las aplicaciones de Xamarin.iOS que se ejecutan en los nuevos dispositivos iPhone 6s y iPhone 6s Plus.

Con 3D Touch, una aplicación de iPhone ahora es capaz de no solo decir que el usuario está tocando la pantalla del dispositivo, pero es capaz de detectar la presión que el usuario está presionando y respondiendo a los diferentes niveles de presión.

3D Touch proporciona las siguientes características a la aplicación:

  • Sensibilidad a la presión: las aplicaciones ahora pueden medir la fuerza con la que el usuario toca la pantalla y aprovechar esa información. Por ejemplo, una aplicación de dibujo puede hacer que una línea sea más gruesa o más fina en función de la fuerza con la que el usuario toca la pantalla.
  • Peek and Pop: ahora la aplicación puede permitir que el usuario interactúe con sus datos sin tener que navegar fuera de su contexto actual. Al presionar de forma dura en la pantalla, pueden ver el elemento en el que están interesados (como obtener una vista previa de un mensaje). Al presionar más duro, pueden entrar en el elemento.
  • Acciones rápidas: imagine que Acciones rápidas son como los menús contextuales que aparecen cuando un usuario hace clic con el botón derecho en un elemento de una aplicación de escritorio. Con Acciones rápidas, puede agregar accesos directos a las funciones de la aplicación directamente desde el icono de la aplicación en la pantalla Inicio.
  • Probar 3D Touch en el simulador: con el hardware Mac correcto, puede probar aplicaciones habilitadas para 3D Touch en el simulador de iOS.

Sensibilidad a la presión

Como se indicó anteriormente, mediante el uso de nuevas propiedades de la clase UITouch puede medir la cantidad de presión que el usuario está aplicando a la pantalla del dispositivo iOS y usar esta información en la interfaz de usuario. Por ejemplo, hacer que un trazo de pincel sea más translúcido o opaco en función de la cantidad de presión.

Un trazo de pincel representado como más translúcido o opaco en función de la cantidad de presión

Como resultado de 3D Touch, si la aplicación se ejecuta en iOS 9 (o superior) y el dispositivo iOS es capaz de admitir 3D Touch, los cambios en la presión harán que se genere el evento TouchesMoved.

Por ejemplo, al supervisar el evento TouchesMoved de un UIView, puede usar el código siguiente para obtener la presión actual que el usuario está aplicando a la pantalla:

public override void TouchesMoved (NSSet touches, UIEvent evt)
{
    base.TouchesMoved (touches, evt);
    UITouch touch = touches.AnyObject as UITouch;
    if (touch != null)
    {
        // Get the pressure
        var force = touch.Force;
        var maxForce = touch.MaximumPossibleForce;

        // Do something with the touch and the pressure
        ...
    }
}

La propiedad MaximumPossibleForce devuelve el valor más alto posible para la propiedad Force del UITouch en función del dispositivo iOS en el que se ejecuta la aplicación.

Importante

Los cambios en la presión harán que se genere el evento TouchesMoved, incluso si las coordenadas X/Y no han cambiado. Debido a este cambio de comportamiento, las aplicaciones de iOS deben estar preparadas para que el evento TouchesMoved se invoque con más frecuencia y que las coordenadas X/Y sean las mismas que la última llamada de TouchesMoved.

Para obtener más información, consulta la TouchCanvas de Apple: Usar UITouch de forma eficiente y eficaz aplicación de ejemplo y Referencia de clase UITouch.

Inspección y pop

3D Touch proporciona nuevas formas para que un usuario interactúe con información dentro de la aplicación más rápido que nunca, sin tener que navegar desde su ubicación actual.

Por ejemplo, si la aplicación muestra una tabla de mensajes, el usuario puede presionar duro en un elemento para obtener una vista previa de su contenido en una vista superpuesta (a lo que Apple hace referencia como un Peek).

Un ejemplo de inspección del contenido

Si el usuario presiona más duro, escribirá la vista de mensaje normal (que se conoce como Pop-ping en la vista).

Comprobación de la disponibilidad táctil 3D

Al trabajar con un UIViewController, puede usar el siguiente código para ver si el dispositivo iOS en el que se ejecuta la aplicación es compatible con 3D Touch:

public override void TraitCollectionDidChange(UITraitCollection previousTraitCollection)
{
    //Important: call the base function
    base.TraitCollectionDidChange(previousTraitCollection);

    //See if the new TraitCollection value includes force touch
    if (TraitCollection.ForceTouchCapability == UIForceTouchCapability.Available) {
        //Do something with 3D touch, for instance...
        RegisterForPreviewingWithDelegate (this, View);
        ...

Se puede llamar a este método antes de o después deViewDidLoad().

Control de inspección y pop

En un dispositivo iOS que puede controlar 3D Touch, podemos usar una instancia de la clase UIViewControllerPreviewingDelegate para controlar la visualización de detalles de los elementos Peek y Pop. Por ejemplo, si teníamos un controlador de vista de tabla denominado MasterViewController podríamos usar el siguiente código para admitir Peek y Pop:

using System;
using System.Collections.Generic;
using UIKit;
using Foundation;
using CoreGraphics;

namespace DTouch
{
    public class PreviewingDelegate : UIViewControllerPreviewingDelegate
    {
        #region Computed Properties
        public MasterViewController MasterController { get; set; }
        #endregion

        #region Constructors
        public PreviewingDelegate (MasterViewController masterController)
        {
            // Initialize
            this.MasterController = masterController;
        }

        public PreviewingDelegate (NSObjectFlag t) : base(t)
        {
        }

        public PreviewingDelegate (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        /// Present the view controller for the "Pop" action.
        public override void CommitViewController (IUIViewControllerPreviewing previewingContext, UIViewController viewControllerToCommit)
        {
            // Reuse Peek view controller for details presentation
            MasterController.ShowViewController(viewControllerToCommit,this);
        }

        /// Create a previewing view controller to be shown at "Peek".
        public override UIViewController GetViewControllerForPreview (IUIViewControllerPreviewing previewingContext, CGPoint location)
        {
            // Grab the item to preview
            var indexPath = MasterController.TableView.IndexPathForRowAtPoint (location);
            var cell = MasterController.TableView.CellAt (indexPath);
            var item = MasterController.dataSource.Objects [indexPath.Row];

            // Grab a controller and set it to the default sizes
            var detailViewController = MasterController.Storyboard.InstantiateViewController ("DetailViewController") as DetailViewController;
            detailViewController.PreferredContentSize = new CGSize (0, 0);

            // Set the data for the display
            detailViewController.SetDetailItem (item);
            detailViewController.NavigationItem.LeftBarButtonItem = MasterController.SplitViewController.DisplayModeButtonItem;
            detailViewController.NavigationItem.LeftItemsSupplementBackButton = true;

            // Set the source rect to the cell frame, so everything else is blurred.
            previewingContext.SourceRect = cell.Frame;

            return detailViewController;
        }
        #endregion
    }
}

El GetViewControllerForPreview método se usa para realizar la operación Peek. Obtiene acceso a la celda de la tabla y a los datos de respaldo y, a continuación, carga DetailViewController desde el guión gráfico actual. Al establecer el PreferredContentSize en (0,0) se solicita el tamaño predeterminado de vista de Peek. Por último, desenfocamos todo, pero la celda que estamos mostrando con previewingContext.SourceRect = cell.Frame y devolvimos la nueva vista para mostrar.

El CommitViewController reutiliza la vista que creamos en el Peek para la vista de Pop cuando el usuario presiona más difícil.

Registro para Peek y Pop

Desde el controlador de vista de donde queremos permitir que el usuario Peek y Pop elementos, es necesario registrarse para este servicio. En el ejemplo anterior de un controlador de vista de tabla (MasterViewController), usaríamos el código siguiente:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // Check to see if 3D Touch is available
    if (TraitCollection.ForceTouchCapability == UIForceTouchCapability.Available) {
        // Register for Peek and Pop
        RegisterForPreviewingWithDelegate(new PreviewingDelegate(this), View);
    }
    ...

}

Aquí se llama al método RegisterForPreviewingWithDelegate con una instancia del PreviewingDelegate que creamos anteriormente. En dispositivos iOS que admiten 3D Touch, el usuario puede presionar duro en un elemento para verlo. Si presionan aún más, el elemento aparecerá en la vista de visualización estándar.

Para obtener más información, consulte nuestra aplicación de muestra de Apple ViewControllerPreviews de Apple: Uso de las API de vista previa de UIViewController, Referencia de la clase UIPreviewAction, Referencia de la clase UIPreviewActionGroup y Referencia del protocolo UIPreviewActionItem.

Acciones rápidas

Con 3D Touch y Acciones rápidas, puedes agregar accesos directos comunes, rápidos y fáciles de acceder a las funciones de la aplicación desde el icono de pantalla inicio del dispositivo iOS.

Como se indicó anteriormente, puede considerar acciones rápidas como los menús contextuales que pueden aparecer cuando un usuario hace clic con el botón derecho en un elemento de una aplicación de escritorio. Debe usar Acciones rápidas para proporcionar accesos directos a las funciones o características más comunes de la aplicación.

Ejemplo de un menú Acciones rápidas

Definición de acciones rápidas estáticas

Si una o varias de las acciones rápidas que requiere la aplicación son estáticas y no es necesario cambiarlas, puede definirlas en el archivo Info.plist de la aplicación. Edite este archivo en un editor externo y agregue las siguientes claves:

<key>UIApplicationShortcutItems</key>
<array>
    <dict>
        <key>UIApplicationShortcutItemIconType</key>
        <string>UIApplicationShortcutIconTypeSearch</string>
        <key>UIApplicationShortcutItemSubtitle</key>
        <string>Will search for an item</string>
        <key>UIApplicationShortcutItemTitle</key>
        <string>Search</string>
        <key>UIApplicationShortcutItemType</key>
        <string>com.company.appname.000</string>
    </dict>
    <dict>
        <key>UIApplicationShortcutItemIconType</key>
        <string>UIApplicationShortcutIconTypeShare</string>
        <key>UIApplicationShortcutItemSubtitle</key>
        <string>Will share an item</string>
        <key>UIApplicationShortcutItemTitle</key>
        <string>Share</string>
        <key>UIApplicationShortcutItemType</key>
        <string>com.company.appname.001</string>
    </dict>
</array>

Aquí definimos dos elementos de acción rápida estáticos con las siguientes claves:

  • UIApplicationShortcutItemIconType: define el icono que mostrará el elemento Acción rápida como uno de los siguientes valores:

    • UIApplicationShortcutIconTypeAdd
    • UIApplicationShortcutIconTypeAlarm
    • UIApplicationShortcutIconTypeAudio
    • UIApplicationShortcutIconTypeBookmark
    • UIApplicationShortcutIconTypeCapturePhoto
    • UIApplicationShortcutIconTypeCaptureVideo
    • UIApplicationShortcutIconTypeCloud
    • UIApplicationShortcutIconTypeCompose
    • UIApplicationShortcutIconTypeConfirmation
    • UIApplicationShortcutIconTypeContact
    • UIApplicationShortcutIconTypeDate
    • UIApplicationShortcutIconTypeFavorite
    • UIApplicationShortcutIconTypeHome
    • UIApplicationShortcutIconTypeInvitation
    • UIApplicationShortcutIconTypeLocation
    • UIApplicationShortcutIconTypeLove
    • UIApplicationShortcutIconTypeMail
    • UIApplicationShortcutIconTypeMarkLocation
    • UIApplicationShortcutIconTypeMessage
    • UIApplicationShortcutIconTypePause
    • UIApplicationShortcutIconTypePlay
    • UIApplicationShortcutIconTypeProhibit
    • UIApplicationShortcutIconTypeSearch
    • UIApplicationShortcutIconTypeShare
    • UIApplicationShortcutIconTypeShuffle
    • UIApplicationShortcutIconTypeTask
    • UIApplicationShortcutIconTypeTaskCompleted
    • UIApplicationShortcutIconTypeTime
    • UIApplicationShortcutIconTypeUpdate

    Imágenes UIApplicationShortcutIconType

  • UIApplicationShortcutItemSubtitle: define el subtítulo del elemento.

  • UIApplicationShortcutItemTitle: define el título del elemento.

  • UIApplicationShortcutItemType: es un valor de cadena que usaremos para identificar el elemento en nuestra aplicación. Consulte la sección siguiente para obtener más información.

Importante

No se puede acceder a los elementos de acceso directo de acción rápida que se establecen en el archivo Info.plist con la propiedad Application.ShortcutItems. Solo se pasan al controlador de eventos HandleShortcutItem.

Identificación de elementos de acción rápida

Como ha visto anteriormente, al definir los elementos de acción rápida en la Info.plist de la aplicación, asignó un valor de cadena a la clave de UIApplicationShortcutItemType para identificarlos.

Para que esos identificadores sean más fáciles de trabajar con en el código, agregue una clase denominada ShortcutIdentifier al proyecto de la aplicación y haga que tenga un aspecto similar al siguiente:

using System;

namespace AppSearch
{
    public static class ShortcutIdentifier
    {
        public const string First = "com.company.appname.000";
        public const string Second = "com.company.appname.001";
        public const string Third = "com.company.appname.002";
        public const string Fourth = "com.company.appname.003";
    }
}

Control de una acción rápida

A continuación, debes modificar el archivo AppDelegate.cs de la aplicación para controlar al usuario seleccionando un elemento acción rápida en el icono de la aplicación en la pantalla Inicio.

Haga los siguientes cambios:

using System;
...

public UIApplicationShortcutItem LaunchedShortcutItem { get; set; }

public bool HandleShortcutItem(UIApplicationShortcutItem shortcutItem) {
    var handled = false;

    // Anything to process?
    if (shortcutItem == null) return false;

    // Take action based on the shortcut type
    switch (shortcutItem.Type) {
    case ShortcutIdentifier.First:
        Console.WriteLine ("First shortcut selected");
        handled = true;
        break;
    case ShortcutIdentifier.Second:
        Console.WriteLine ("Second shortcut selected");
        handled = true;
        break;
    case ShortcutIdentifier.Third:
        Console.WriteLine ("Third shortcut selected");
        handled = true;
        break;
    case ShortcutIdentifier.Fourth:
        Console.WriteLine ("Forth shortcut selected");
        handled = true;
        break;
    }

    // Return results
    return handled;
}

public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
    var shouldPerformAdditionalDelegateHandling = true;

    // Get possible shortcut item
    if (launchOptions != null) {
        LaunchedShortcutItem = launchOptions [UIApplication.LaunchOptionsShortcutItemKey] as UIApplicationShortcutItem;
        shouldPerformAdditionalDelegateHandling = (LaunchedShortcutItem == null);
    }

    return shouldPerformAdditionalDelegateHandling;
}

public override void OnActivated (UIApplication application)
{
    // Handle any shortcut item being selected
    HandleShortcutItem(LaunchedShortcutItem);

    // Clear shortcut after it's been handled
    LaunchedShortcutItem = null;
}

public override void PerformActionForShortcutItem (UIApplication application, UIApplicationShortcutItem shortcutItem, UIOperationHandler completionHandler)
{
    // Perform action
    completionHandler(HandleShortcutItem(shortcutItem));
}

En primer lugar, definimos una propiedad LaunchedShortcutItem pública para realizar un seguimiento del último elemento de acción rápida seleccionado por el usuario. A continuación, invalidamos el método FinishedLaunching y vemos si se han pasado launchOptions y si contienen un elemento de acción rápida. Si lo hacen, almacenamos la acción rápida en la propiedad LaunchedShortcutItem.

A continuación, invalidamos el método OnActivated y pasamos cualquier elemento de inicio rápido seleccionado al método HandleShortcutItem en el que actuarán. Actualmente, solo estamos escribiendo un mensaje en la Consola. En una aplicación real, controlaría lo que se necesitaba alguna vez. Una vez realizada la acción, se borra la propiedad LaunchedShortcutItem.

Por último, si la aplicación ya se estaba ejecutando, también se llamaría al método PerformActionForShortcutItem para controlar el elemento Acción rápida, por lo que necesitamos invalidarlo y llamar también a nuestro método HandleShortcutItem.

Crear elementos de acción rápida dinámica

Además de definir elementos de acción rápida estática en el archivo Info.plist de la aplicación, puedes crear acciones rápidas dinámicas sobre la marcha. Para definir dos nuevas acciones rápidas dinámicas, edite de nuevo el archivo AppDelegate.cs y modifique el método FinishedLaunching para que tenga un aspecto similar al siguiente:

public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
    var shouldPerformAdditionalDelegateHandling = true;

    // Get possible shortcut item
    if (launchOptions != null) {
        LaunchedShortcutItem = launchOptions [UIApplication.LaunchOptionsShortcutItemKey] as UIApplicationShortcutItem;
        shouldPerformAdditionalDelegateHandling = (LaunchedShortcutItem == null);
    }

    // Add dynamic shortcut items
    if (application.ShortcutItems.Length == 0) {
        var shortcut3 = new UIMutableApplicationShortcutItem (ShortcutIdentifier.Third, "Play") {
            LocalizedSubtitle = "Will play an item",
            Icon = UIApplicationShortcutIcon.FromType(UIApplicationShortcutIconType.Play)
        };

        var shortcut4 = new UIMutableApplicationShortcutItem (ShortcutIdentifier.Fourth, "Pause") {
            LocalizedSubtitle = "Will pause an item",
            Icon = UIApplicationShortcutIcon.FromType(UIApplicationShortcutIconType.Pause)
        };

        // Update the application providing the initial 'dynamic' shortcut items.
        application.ShortcutItems = new UIApplicationShortcutItem[]{shortcut3, shortcut4};
    }

    return shouldPerformAdditionalDelegateHandling;
}

Ahora comprobamos si el application ya contiene un conjunto de ShortcutItemscreados dinámicamente, si no se crean dos nuevos objetos de UIMutableApplicationShortcutItem para definir los nuevos elementos y agregarlos a la matriz de ShortcutItems.

El código que ya hemos agregado en la sección Control de una acción rápida anterior controlará estas acciones rápidas dinámicas igual que las estáticas.

Se debe tener en cuenta que puede crear una combinación de elementos de acción rápida estática y dinámica (como estamos haciendo aquí), no se limita a uno o al otro.

Para obtener más información, consulte nuestra aplicación de muestra de Apple ApplicationShortcuts: uso de UIApplicationShortcutItem, Referencia de la clase UIApplicationShortcutItem, Referencia de la clase UIMutableApplicationShortcutItem y Referencia de la clase UIApplicationShortcutIcon.

Probar 3D Touch en el simulador

Al usar la versión más reciente de Xcode y el simulador de iOS en un equipo Mac compatible con un trackpad de Force Touch, puede probar la funcionalidad 3D Touch en el simulador.

Para habilitar esta funcionalidad, ejecute cualquier aplicación en hardware simulado de iPhone que admita 3D Touch (iPhone 6 y versiones posteriores). A continuación, seleccione el menú Hardware en el simulador de iOS y habilite el elemento de menú Usar Trackpad Force para 3D Touch:

Seleccione el elemento de menú Hardware en el simulador de iOS y habilite el elemento de menú Usar Trackpad Force para 3D Touch

Con esta característica activa, puedes presionar más duro en el trackpad del Mac para habilitar 3D Touch como lo harías en el hardware real del iPhone.

Resumen

En este artículo se han introducido las nuevas API 3D Touch disponibles en iOS 9 para iPhone 6 y iPhone 6s Plus. Se ha tratado la adición de sensibilidad de presión a una aplicación; usar Peek y Pop para mostrar rápidamente información en la aplicación desde el contexto actual sin navegación; y usar Acciones rápidas para proporcionar accesos directos a las características más usadas de la aplicación.