Animation UISearchController personnalisée

La question du fond:

Comment replace l'animation par défaut pour le rejet d'un searchBar appartenant à un UISearchController?


Comportement du controller de search standard:

Bon alors j'essaye de créer une animation personnalisée pour quand le UISearchBar qui est attaché à un UISearchController devient actif. Il semble que l'animation standard attende que searchBar commence par une largeur qui occupe l'écran. Lorsque l'animation commence, elle rétrécit le searchBar et disparaît dans un button d'annulation à droite de celui-ci.

Ce que je veux réaliser

Je veux que ma barre de search commence dans un petit état, à peu près la moitié de la largeur de l'écran, pour permettre à deux buttons d'être placés dans la barre de navigation à côté de cela.

Animation actuelle:

Lorsque searchBar devient actif, je souhaite que l'animation étende searchBar et que le button d'annulation apparaisse.

Rejet de l'animation:

Lorsque le searchBar est fermé, je veux que l'animation opposée exacte se produise: Annuler le fondu du button et searchBar rétrécir à sa taille d'origine.


Le problème:

J'ai trouvé un moyen d'get l'animation de présentation souhaitée en utilisant une méthode UISearchControllerDelegate, presentSearchController:

func presentSearchController(searchController: UISearchController) { // Animate Buttons UIView.animateWithDuration(0.1, animations: { // First Hide Buttons self.createMoxyButton.alpha = 0 self.centerMapButton.alpha = 0 }) // Animate Search Bar UIView.animateWithDuration(0.5, animations: { // Search Bar searchController.searchBar.frame = CGRectMake(searchController.searchBar.frame.origin.x, searchController.searchBar.frame.origin.y, self.wBounds - 40, searchController.searchBar.frame.height) self }) } 

mais je n'ai pas pu réaliser l'animation de licenciement. J'ai essayé d'utiliser les methods didDismissSearchController: et willDismissSearchController: delegate mais il en résulte un comportement bizarre et n'utilise pas l'animation des frameworks que j'ai définis dans ces methods déléguées respectives. Lorsque le searchBar est fermé, il s'étendra jusqu'à la largeur de l'écran, tandis que le button d'annulation disparaitra, il passera immédiatement à la taille de la barre de search, ignorant ainsi mon animation. J'ai également essayé d'utiliser la méthode removeAllAnimation () pour essayer d'arrêter l'animation par défaut, mais en vain.

 func didDismissSearchController(searchController: UISearchController) { searchController.searchBar.layer.removeAllAnimations() // Animate UIView.animateWithDuration(0.5, animations: { // Show hidden buttons self.createMoxyButton.alpha = 1 self.centerMapButton.alpha = 1 // Search Bar searchController.searchBar.frame = CGRectMake(searchController.searchBar.frame.origin.x, searchController.searchBar.frame.origin.y, self.wBounds - 10 - self.createMoxyButton.frame.size.width - 20 - self.centerMapButton.frame.size.width - 20, searchController.searchBar.frame.height) self }) } 

Image du problème rejetant SearchBar

Gif Animation commence avec searchBar dans l'état Active avec le button d'annulation visible

Gif Animation commence avec searchBar dans l'état Active avec le bouton d'annulation visible

Sous-class UISearchController et implémenter la méthode facultative UIViewControllerTransitioningDelegate - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;

pour renvoyer votre object d'animation pour faire l'animation pour le rejet.

Je ne peux pas prétendre que cela produit une animation super lisse, mais cela n'a pas l'air terrible et pourrait être utile (ou même exactement ce dont vous avez besoin). Si vous voulez l'essayer, vous pouvez créer un nouveau projet (application à vue unique) et append le controller de navigation en tant que premier et l'object de la class ViewController tant que controller racine (juste pour get rapidement la barre de navigation). Le code ci-dessous est l'set de mon implémentation de ViewController

 import UIKit class ViewController: UIViewController,UISearchBarDelegate,UISearchControllerDelegate,UISearchResultsUpdating { lazy var createMoxyButton:UIBarButtonItem = { //customize this as your equire let button = UIBarButtonItem(title: "Done", style: .Plain, target: nil, action: nil) return button }() lazy var centerMapButton:UIBarButtonItem = { //customize this as your equire let button = UIBarButtonItem(title: "Done", style: .Plain, target: nil, action: nil) return button }() lazy var searchController:UISearchController = { let controller = UISearchController(searchResultsController: self) controller.delegate = self controller.searchResultsUpdater = self controller.dimsBackgroundDuringPresentation = false controller.hidesNavigationBarDuringPresentation = false return controller }() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.navigationItem.titleView = self.searchController.searchBar self.navigationItem.rightBarButtonItems = [self.centerMapButton,self.createMoxyButton] self.edgesForExtendedLayout = UIRectEdge.None self.searchController.searchBar.delegate = self } func updateSearchResultsForSearchController(searchController: UISearchController) { } func searchBarTextDidBeginEditing(searchBar: UISearchBar) { //this needs to be done because in shouldEndEditing //we need to set it to false to smooth animation searchBar.showsCancelButton = true self.navigationItem.setRightBarButtonItems(nil, animated: true) } func searchBarShouldEndEditing(searchBar: UISearchBar) -> Bool { searchBar.showsCancelButton = false self.navigationItem.rightBarButtonItems = [self.centerMapButton,self.createMoxyButton] return true } }