Hola a todos, mi nombre es Denis, estamos desarrollando un servicio de análisis de suscripción para aplicaciones iOS: Apphud .
En WWDC 2019, Apple introdujo una nueva forma de interactuar con la interfaz de su aplicación: menús contextuales . Se ven así:

En este artículo consideraremos algunas de las sutilezas de su uso y aprenderemos cómo hacerlas.
Los menús contextuales son una continuación lógica de la tecnología "Peek and Pop", cuando el usuario puede abrir una vista previa de un elemento presionándolo con fuerza. Pero entre ellos hay varias diferencias significativas.
Los menús contextuales funcionan en cualquier dispositivo con iOS 13. No se requiere soporte táctil 3D del dispositivo. Por lo tanto, en particular, se pueden usar en todos los iPad.
Los botones que le permiten interactuar con el elemento aparecen de inmediato y no requieren deslizar hacia arriba.
Para abrir el menú contextual, el usuario solo necesita mantener el dedo sobre el elemento deseado o presionarlo con fuerza (si el dispositivo es compatible con 3D Touch).
Recomendaciones al usar menús contextuales
Las pautas de interfaz humana de Apple recomiendan que siga estas pautas al diseñar menús contextuales.
Diseñar correctamente
No será bueno si agrega un menú para algunos elementos en algunos lugares y no lo agrega para elementos similares en otros. Entonces el usuario pensará que la aplicación no funciona correctamente.
Incluya solo lo necesario en el menú
El menú contextual es un gran lugar para los comandos más utilizados. "Muy a menudo" es una frase clave. No agregue todo en una fila.
Usar submenús
Use los submenús para facilitar la navegación del usuario. Dé a los elementos del menú nombres simples y claros.
No use más de 1 nivel de anidamiento
A pesar de que los submenús pueden facilitar la navegación, pueden complicarla fácilmente. Apple no recomienda usar más de 1 nivel de anidamiento.
Coloca los artículos usados con más frecuencia en la parte superior
Las personas se centran principalmente en la parte superior del menú, por lo que les resulta un poco más fácil navegar por su aplicación.
Usar agrupación
Agrupe elementos de menú similares
Evite usar el menú contextual y el menú de edición en el mismo elemento al mismo tiempo
Pueden entrar en conflicto entre sí, porque ambos se llaman en un toque largo.

No agregue un botón separado "Abrir" en el menú
Los usuarios pueden abrir un elemento simplemente tocándolo. Un botón adicional "Abrir" será superfluo.
El menú contextual más simple para UIView
Ahora que hemos aprendido las reglas básicas para usar menús contextuales, pasemos a practicar. Por supuesto, los menús solo funcionan en iOS 13 y superior, y para la prueba necesitará Xcode 11. Puede descargar la versión beta de Xcode 11 aquí .
UIImageView
un menú contextual, por ejemplo, en un UIImageView
, como en la animación anterior .
Para hacer esto, simplemente agregue el objeto UIImageView
al controlador y escriba algunas líneas de código, por ejemplo, en el método viewDidLoad
:
class SingleViewController: UIViewController { @IBOutlet var imageView: UIImageView! override func viewDidLoad() { super.viewDidLoad() imageView.isUserInteractionEnabled = true let interaction = UIContextMenuInteraction(delegate: self) imageView.addInteraction(interaction) } }
UIContextMenuInteraction
, se UIContextMenuInteraction
un objeto de la clase UIContextMenuInteraction
. El constructor requiere que especifique el delegado que será responsable del menú. Volvamos a esto un poco más tarde. Y con el método addInteraction
agregamos nuestro menú a la imagen.
Ahora queda por implementar el protocolo UIContextMenuInteractionDelegate
. Solo tiene un método obligatorio que se encarga de crear el menú:
extension SingleViewController: UIContextMenuInteractionDelegate { func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? { let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { actions -> UIMenu<UIAction>? in let save = UIAction(__title: "My Button", image: nil, options: []) { action in
Si nil
devuelve nil
en este método, no se llamará al menú contextual. Dentro del método mismo, creamos un objeto de la clase UIContextMenuConfiguration
. Al crear, pasamos estos parámetros:
identifier
: identificador del menú.
previewProvider
es un controlador personalizado que se puede mostrar opcionalmente en lugar del elemento actual en el menú. Consideraremos esto un poco más tarde.
en actionProvider
pasamos los elementos del menú contextual.
Los elementos en sí mismos se crean simplemente en ninguna parte: indican el nombre, un icono opcional y un controlador para hacer clic en un elemento del menú. Eso es todo!
Agregar un submenú
Vamos a complicar un poco las cosas. Agregue a nuestra imagen un menú con dos elementos: "Guardar" y "Editar ...". Al hacer clic en "Editar ..." se abre un submenú con los elementos "Rotar" y "Eliminar". Debería verse así:

Para hacer esto, reescriba el método de protocolo UIContextMenuInteractionDelegate
siguiente manera:
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? { let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { actions -> UIMenu<UIAction>? in
Aquí creamos sucesivamente los botones "Guardar", "Girar" y "Eliminar", agregamos los dos últimos al submenú "Editar ..." y ajustamos todo en el menú contextual principal.
Agregar menú contextual a UICollectionView
UICollectionView
un menú contextual a UICollectionView
. Con una pulsación larga en la celda, se mostrará al usuario un menú con el elemento "Archivo", como este:

Agregar un menú contextual a un UICollectionView
es simple: simplemente implemente el método opcional de func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration?
Protocolo UICollectionViewDelegate
. Esto es lo que tenemos:
override func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { actions -> UIMenu<UIAction>? in let action = UIAction(__title: "Archive", image: UIImage(systemName: "archivebox.fill"), options: .destructive) { action in
Aquí, como antes, se crean el elemento y el menú en sí. Ahora, con un clic largo (fuerte) en una celda, el usuario verá un menú contextual.
Agregar menú contextual a UITableView
Todo aquí es similar a UICollectionView
. contextMenuConfigurationForRowAt
implementar el método UITableViewDelegate
protocolo UITableViewDelegate
esta manera:
override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { actions -> UIMenu<UIAction>? in let action = UIAction(__title: "Custom action", image: nil, options: []) { action in
Pero, ¿qué pasa si queremos usar una pantalla personalizada en el menú contextual? Por ejemplo, esto:

Para hacer esto, al crear una UIContextMenuConfiguration
debe pasar el UIViewController
deseado a previewProvider
. Aquí hay un ejemplo de código que implementa esto:
class PreviewViewController: UIViewController { static func controller() -> PreviewViewController { let storyboard = UIStoryboard(name: "Main", bundle: nil) let controller = storyboard.instantiateViewController(withIdentifier: "PreviewViewController") as! PreviewViewController return controller } } extension TableViewController: UITableViewDelegate { override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: { () -> UIViewController? in
En el ejemplo, PreviewViewController
inicializa desde el guión gráfico y se muestra en el menú contextual.
Queda por agregar el procesamiento de clics a este ViewController. Para hacer esto, implemente el método UITableViewDelegate
protocolo UITableViewDelegate
. El controlador en sí se colocará dentro de animator.addCompletion
:
override func tableView(_ tableView: UITableView, willCommitMenuWithAnimator animator: UIContextMenuInteractionCommitAnimating) { animator.addCompletion {
Conclusión
Los menús contextuales son una nueva herramienta poderosa para la interacción del usuario con su aplicación. Y, como puede ver, su implementación es bastante simple. Pero no debe olvidar que los métodos pueden cambiar hasta que se lance la versión de lanzamiento de iOS 13.
¿Desea implementar suscripciones en su aplicación iOS en 10 minutos? Integra Apphud y:
- Haga compras usando solo un método;
- rastrea automáticamente el estado de la suscripción de cada usuario;
- Integre ofertas de suscripción fácilmente
- enviar eventos de suscripción a Amplitude, Mixpanel, Slack y Telegram teniendo en cuenta la moneda local del usuario;
- disminuir la tasa de abandono en las aplicaciones y devolver a los usuarios no suscritos.
Que leer