Comment implémenter les menus contextuels dans iOS 13

Bonjour à tous, je m'appelle Denis, nous développons un service d'analyse d'abonnement pour les applications iOS - Apphud .


Lors de la WWDC 2019, Apple a présenté une nouvelle façon d'interagir avec l'interface de votre application: les menus contextuels . Ils ressemblent à ceci:



Dans cet article, nous allons examiner certaines des subtilités de leur utilisation et apprendre à les fabriquer.


Les menus contextuels sont une continuation logique de la technologie «Peek and Pop», lorsque l'utilisateur pouvait ouvrir un aperçu d'un élément en appuyant dessus. Mais entre eux, il existe plusieurs différences importantes.


  • Les menus contextuels fonctionnent sur tout appareil exécutant iOS 13. Aucune prise en charge tactile 3D n'est requise de l'appareil. Par conséquent, en particulier, ils peuvent être utilisés sur tous les iPad.


  • Les boutons qui vous permettent d'interagir avec l'élément apparaissent immédiatement et ne nécessitent pas de balayage vers le haut.



Pour ouvrir le menu contextuel, l'utilisateur a juste besoin de tenir votre doigt sur l'élément souhaité ou d'appuyer dessus (si l'appareil prend en charge 3D Touch).


Recommandations lors de l'utilisation des menus contextuels


Les directives d'interface humaine d'Apple vous recommandent de suivre ces directives lors de la conception des menus contextuels.


Concevoir correctement


Ce ne sera pas bon si vous ajoutez un menu pour certains éléments à certains endroits et ne l'ajoutez pas pour des éléments similaires dans d'autres. L'utilisateur pensera alors que l'application ne fonctionne pas correctement.


Inclure uniquement le nécessaire dans le menu


Le menu contextuel est un endroit idéal pour les commandes les plus couramment utilisées. «Le plus souvent» est une phrase clé. N'ajoutez pas tout de suite.


Utiliser des sous-menus


Utilisez les sous-menus pour faciliter la navigation de l'utilisateur. Donnez aux éléments de menu des noms simples et clairs.


N'utilisez pas plus d'un niveau d'imbrication


Malgré le fait que les sous-menus peuvent faciliter la navigation, ils peuvent facilement la compliquer. Apple ne recommande pas d'utiliser plus d'un niveau d'imbrication.


Mettez les articles les plus fréquemment utilisés en haut


Les utilisateurs se concentrent principalement sur le haut du menu, il leur est donc plus facile de naviguer dans votre application.


Utiliser le regroupement


Regrouper les éléments de menu similaires


Évitez d'utiliser le menu contextuel et le menu d'édition sur le même élément en même temps


Ils peuvent entrer en conflit les uns avec les autres, car les deux sont appelés en appuyant longuement.


Menu d'édition IOS


N'ajoutez pas de bouton «Ouvrir» distinct dans le menu


Les utilisateurs peuvent ouvrir un élément en appuyant simplement dessus. Un bouton supplémentaire «Ouvrir» sera superflu.


Le menu contextuel le plus simple pour UIView


Maintenant que nous avons appris les règles de base pour utiliser les menus contextuels, passons à la pratique. Bien sûr, les menus ne fonctionnent que sur iOS 13 et supérieur, et pour les tests, vous aurez besoin de Xcode 11. Vous pouvez télécharger la version bêta de Xcode 11 ici .


Vous pouvez télécharger l'exemple complètement ici .


Ajoutons un menu contextuel, par exemple, sur un UIImageView , comme dans l'animation ci-dessus .


Pour ce faire, ajoutez simplement l'objet UIImageView au contrôleur et écrivez quelques lignes de code, par exemple, dans la méthode 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 , un objet de la classe UIContextMenuInteraction est UIContextMenuInteraction . Le constructeur vous demande de spécifier le délégué qui sera responsable du menu. Revenons un peu plus tard. Et avec la méthode addInteraction nous ajoutons notre menu à l'image.


Reste maintenant à implémenter le protocole UIContextMenuInteractionDelegate . Il n'a qu'une seule méthode obligatoire qui est responsable de la création du menu:


 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 // Put button handler here } return configuration } } 

Si nil retourné dans cette méthode, le menu contextuel ne sera pas appelé. À l'intérieur de la méthode elle-même, nous créons un objet de la classe UIContextMenuConfiguration . Lors de la création, nous transmettons ces paramètres:


  • identifier - identifiant du menu.


  • previewProvider est un contrôleur personnalisé qui peut éventuellement être affiché à la place de l'élément actuel dans le menu. Nous y réfléchirons un peu plus tard.


  • dans actionProvider nous passons les éléments du menu contextuel.



Les éléments eux-mêmes sont créés simplement nulle part: ils indiquent le nom, une icône facultative et un gestionnaire pour cliquer sur un élément de menu. C'est tout!


Ajouter un sous-menu


Compliquons un peu les choses. Ajoutez à notre image un menu avec deux éléments: "Enregistrer" et "Modifier ...". En cliquant sur "Modifier ...", un sous-menu s'ouvre avec les éléments "Rotation" et "Supprimer". Cela devrait ressembler à ceci:



Pour ce faire, réécrivez la méthode de protocole UIContextMenuInteractionDelegate comme suit:


 func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? { let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { actions -> UIMenu<UIAction>? in // Creating Save button let save = UIAction(__title: "Save", image: UIImage(systemName: "tray.and.arrow.down.fill"), options: []) { action in // Just showing some alert self.showAlert(title: action.title) } // Creating Rotate button let rotate = UIAction(__title: "Rotate", image: UIImage(systemName: "arrow.counterclockwise"), options: []) { action in self.showAlert(title: action.title) } // Creating Delete button let delete = UIAction(__title: "Delete", image: UIImage(systemName: "trash.fill"), options: .destructive) { action in self.showAlert(title: action.title) } // Creating Edit, which will open Submenu let edit = UIMenu<UIAction>.create(title: "Edit...", children: [rotate, delete]) // Creating main context menu return UIMenu<UIAction>.create(title: "Menu", children: [save, edit]) } return configuration } 

Ici, nous créons successivement les boutons "Enregistrer", "Rotation" et "Supprimer", ajoutons les deux derniers au sous-menu "Modifier ..." et enveloppons le tout dans le menu contextuel principal.


Ajouter un menu contextuel à UICollectionView


Ajoutons un menu contextuel à l' UICollectionView . Avec un appui long sur la cellule, l'utilisateur affichera un menu avec l'élément «Archive», comme ceci:



L'ajout d'un menu contextuel à UICollectionView est simple: implémentez simplement la méthode facultative func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? Protocole UICollectionViewDelegate . Voici ce que nous avons obtenu:


 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 // Put button handler here } return UIMenu<UIAction>.create(title: "Menu", children: [action]) } return configuration } 

Ici, comme précédemment, l'élément et le menu lui-même sont créés. Maintenant, avec un clic long (fort) sur une cellule, l'utilisateur verra un menu contextuel.


Ajouter un menu contextuel à UITableView


Tout ici est similaire à UICollectionView . Vous devez implémenter la méthode UITableViewDelegate protocole UITableViewDelegate comme ceci:


 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 // Put button handler here } return UIMenu<UIAction>.create(title: "Menu", children: [action]) } return configuration } 

Mais que se passe-t-il si nous voulons utiliser un écran personnalisé dans le menu contextuel? Par exemple, ceci:



Pour ce faire, lors de la création d'une UIContextMenuConfiguration devez transmettre l' UIViewController souhaité à previewProvider . Voici un exemple de code qui implémente ceci:


 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 // Return Preview View Controller here return PreviewViewController.controller() }) { _ -> UIMenu<UIAction>? in let action = UIAction(__title: "Custom action", image: nil, options: []) { action in // Put button handler here } return UIMenu<UIAction>.create(title: "Menu", children: [action]) } return configuration } } 

Dans l'exemple, PreviewViewController initialisé à partir du storyboard et affiché dans le menu contextuel.


Il reste à ajouter le traitement des clics à ce ViewController. Pour ce faire, implémentez la méthode UITableViewDelegate protocole UITableViewDelegate . Le gestionnaire lui-même sera placé dans animator.addCompletion :


 override func tableView(_ tableView: UITableView, willCommitMenuWithAnimator animator: UIContextMenuInteractionCommitAnimating) { animator.addCompletion { // Put handler here } } 

Conclusion


Les menus contextuels sont un nouvel outil puissant pour l'interaction de l'utilisateur avec votre application. Et, comme vous pouvez le voir, leur mise en œuvre est assez simple. Mais vous ne devez pas oublier que les méthodes peuvent changer jusqu'à la sortie de la version finale d'iOS 13.


Vous souhaitez mettre en œuvre des abonnements dans votre application iOS en 10 minutes? Intégrez Apphud et:
  • Faites des achats en utilisant une seule méthode;
  • suivre automatiquement l'état de l'abonnement de chaque utilisateur;
  • Intégrez facilement les offres d'abonnement
  • envoyer des événements d'abonnement à Amplitude, Mixpanel, Slack et Telegram en tenant compte de la devise locale de l'utilisateur;
  • diminuer le taux de désabonnement dans les applications et renvoyer les utilisateurs non abonnés.


Que lire?


Source: https://habr.com/ru/post/fr455854/


All Articles