Split Controller sans ces storyboards

Auparavant, ils ont créé un xib distinct pour prendre en charge l'iPad. Pour unifier la mise en page, Apple a introduit en 2014 la mise en page automatique et les classes de taille, et pour la navigation adaptative UISplitViewController .



Un contrôleur divisé est un conteneur qui place deux contrôleurs côte à côte. Sur la gauche, il y aura un contrôleur de navigation (pas sur le contrôleur de navigation), sur la droite correspondant au choix dans la navigation. Bref, comme dans Paramètres.


Voyons comment configurer UISplitViewController et son comportement sur les écrans.


Définition des contrôleurs


Désignez les contrôleurs gauche (navigation) et droit. Pour les deux, définissez l'en-tête:


 class MasterController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() self.navigationItem.title = "Master" self.navigationController?.navigationBar.prefersLargeTitles = true } } class DetailController: UIViewController { override func viewDidLoad() { super.viewDidLoad() self.navigationItem.title = "Detail" self.navigationController?.navigationBar.prefersLargeTitles = true } } 

Un contrôleur divisé est un conteneur pour deux contrôleurs. Comme je l'ai écrit avant le kat, à gauche se trouve le contrôleur de navigation principal, à droite correspondant au choix dans la navigation, ou détaillé (contrôleur de détail). N'oubliez pas Master et Detail, les mots seront trouvés dans la documentation et les protocoles.


Ajouter un fractionnement


Passons à AppDelegate, dans la méthode didFinishLaunchingWithOptions, créons une nouvelle fenêtre, initialisons le contrôleur Split et deux autres, définissez-le sur Split:


 let masterController = MasterController() let masterNavigationController = UINavigationController(rootViewController: masterController) let detailController = DetailController() let detailNavigationController = UINavigationController(rootViewController: detailController) let splitViewController = UISplitViewController() splitViewController.viewControllers = [masterNavigationController, detailNavigationController] self.window = UIWindow(frame: UIScreen.main.bounds) self.window!.rootViewController = splitViewController self.window!.makeKeyAndVisible() 

Exécutez le simulateur. Orientations portrait et paysage respectivement:



Dans l'orientation du port, le contrôleur maître n'est pas visible. Balayez vers la gauche pour le faire apparaître. Il est configuré à l'aide de modes, nous les analyserons plus en détail.



Ajoutez des cellules au contrôleur maître. Permettez-moi de vous rappeler qu'un contrôleur maître est une table enveloppée dans un UINavigationController.


Vous savez comment ajouter des cellules, vous n'avez pas besoin de regarder le code
 class MasterController: UITableViewController { override func viewDidLoad() { self.tableView = UITableView(frame: .zero, style: .insetGrouped) super.viewDidLoad() self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "id") self.navigationItem.title = "Master" self.navigationController?.navigationBar.prefersLargeTitles = true } override func numberOfSections(in tableView: UITableView) -> Int { return 2 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 4 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "id")! cell.textLabel?.text = "\(indexPath)" return cell } } 

Et si vous ne savez pas comment, alors ici .


Dans iOS 13, un nouveau style de tableau .insetGrouped est apparu , je l'ai installé. Le style est disponible à partir de Xcode 11.


Exécutez le projet:



En cliquant sur la cellule, nous afficherons un contrôleur détaillé. Comment les "contrôleurs détaillés" ont coupé la rumeur , j'espère que dans les commentaires, dites-moi mieux la traduction. Le code ressemble à ceci:


 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let controller = DetailController() controller.navigationTitle = "\(indexPath)" self.showDetailViewController(UINavigationController(rootViewController: controller), sender: nil) } 

N'oubliez pas de nommer les contrôleurs maître / détaillé? Voici un exemple d'utilisation de Detail dans la méthode showDetailViewController .


Attentif remarquera que le contrôleur n'a pas navigationTitle . Mettez à jour la classe du contrôleur de détail:


 class DetailController: UIViewController { var navigationTitle: String = "Detail" override func viewDidLoad() { super.viewDidLoad() self.navigationItem.title = navigationTitle self.view.backgroundColor = .white } } 

Exécutez le projet et cliquez sur la cellule:



IPhones


La navigation est adaptative, ce qui signifie que tout est prêt. Enfin presque. Sélectionnez un iPhone et exécutez:



Fonctionne comme un contrôleur de navigation classique. C'est universalité adaptabilité - en fonction de l'espace libre, le contrôleur Split place les contrôleurs principaux et détaillés.


Pas le contrôleur maître, mais Detail a été le premier à s'ouvrir sur l'iPhone. La transition entre l'affichage de deux contrôleurs et une situation similaire est configurée par le délégué UISplitViewControllerDelegate . La valeur de retour détermine s'il faut afficher le contrôleur maître ou Détail:


 extension AppDelegate: UISplitViewControllerDelegate { func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool { return true } } 

Cette méthode ne doit pas toujours renvoyer true. Exemple: lors du changement d'orientation vers un contrôleur de détail compact et déjà ouvert, vous devrez peut-être laisser Détail sur l'écran. Planifiez ce comportement.



Paysage pour iPhone


L'orientation paysage pour les iPhones fonctionne sans Split par défaut. Ceci est corrigé par le mode d'affichage du contrôleur Split:


 splitViewController.preferredDisplayMode = UISplitViewController.DisplayMode.allVisible 

Nous définissons le mode d'affichage préféré, à savoir pour afficher la paire Master-Detail chaque fois que possible. La capacité détermine l'API, il est impossible de configurer.


En orientation portrait restera le même. Mais dans le paysage (uniquement pour Xs Max et 8+):



Si les conditions du contrôleur Split changent dans le SDK, votre projet les implémentera par défaut.


Les dimensions


Peut être personnalisé. Cela se fait par le rapport d'aspect:


 splitViewController.preferredPrimaryColumnWidthFraction = 0.5 splitViewController.maximumPrimaryColumnWidth = 2000 

Master et Detail seront de la même taille. Veillez à définir maximumPrimaryColumnWidth . En option, vous pouvez définir la largeur minimale. Je n'ajouterai pas de capture d'écran, et il y a tellement d'ipads pour le tutoriel)


Masquer le maître


Ajoutez un bouton qui ouvre Détail en plein écran. Le contrôleur divisé doit être en mode .allVisible . Collez le code du contrôleur Detail dans viewDidLoad :


 if let splitController = self.splitViewController{ if let navController = splitController.viewControllers.last as? UINavigationController { navController.topViewController?.navigationItem.leftBarButtonItem = splitController.displayModeButtonItem } } 

Il est difficile de décrire le comportement, et le gif est la taille d'un budget de Moscou. Donc une capture d'écran:



Ou j'ai une vidéo sur Twitter .


Lignes directrices


AutoLayout place les éléments, le contrôleur Split détermine la navigation. Apple recommande fortement d'utiliser un contrôleur maître statique . Par souci d'expérience, j'ai fait un contrôleur de navigation sur la gauche, en cliquant sur une cellule j'ai poussé les contrôleurs (au lieu de mettre à jour le contrôleur Détail). Ça a l'air bizarre.


En règle générale, limitez la navigation à un côté d'une vue fractionnée. Le fait de placer la navigation dans les deux volets d'une vue fractionnée rend difficile pour les utilisateurs de rester orientés et de discerner la relation entre les deux volets.

Mettez en surbrillance la sélection active dans le contrôleur maître. Bien que le contenu du contrôleur de détail puisse varier, il doit toujours correspondre à la sélection sur le maître. Cela aidera les gens à contrôler la relation entre les contrôleurs. Pour contrôler les contrôleurs - un jeu de mots en quelque sorte.


Pas besoin d'utiliser Split partout. Mais si votre application dispose d'une navigation solide et que le contrôleur racine est Tab ou Navigation, Split est très probablement utile. Si vous avez une application de traduction à écran unique, vous n'avez pas besoin de Split.


Pour les demandeurs


Lien vers la documentation , lien vers les directives .
Si vous préférez regarder la vidéo, consultez le tutoriel:


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


All Articles