自定义UISearchControlleranimation

底线问题:

如何覆盖属于UISearchController的searchBar的默认animation?


标准search控制器行为:

好的,所以我试图创build一个自定义的animation,当附加到UISearchController UISearchBar成为活动。 看起来标准animation期望searchBar以占用屏幕的宽度开始。 当animation开始时,缩小search栏并淡入其右侧的取消button。

我想达到什么:

我想让我的searchBar以一个很小的状态开始,大约是屏幕宽度的一半,以允许两个button放在旁边的导航栏中。

现在animation:

当searchBar变为活动状态时,我想让animation展开searchBar,并取消button淡入。

解散animation:

当searchBar被解散时,我想要相反的animation发生:取消button淡出和searchBar收缩到原来的大小。


问题:

我find了一种通过使用UISearchControllerDelegate方法presentSearchController实现所需的呈现animation的方法:

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 }) } 

但是我一直无法做到解雇animation。 我曾尝试使用didDismissSearchController:和willDismissSearchController:委托方法,但它会导致奇怪的行为,并不使用我在这些相应的委托方法中设置的框架的animation。 当searchBar被解除时,它会扩展到全屏宽度,淡出取消button,那么它会立即将searchBar的框架改回到原始大小,忽略我的animation。 我也尝试使用removeAllAnimation()方法来尝试停止发生的默认animation,但无济于事。

 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 }) } 

问题closuresSearchBar的图像

Gifanimation以处于活动状态的searchBar开始,取消button可见

Gif动画以处于活动状态的searchBar开始,取消按钮可见

子类UISearchController和实现可选的UIViewControllerTransitioningDelegate方法- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;

返回你的animation对象做解雇的animation。

我不能说这会产生超级stream畅的animation,但它看起来并不可怕,并且可能会有所帮助(或者甚至是你所需要的)。 如果你想尝试一下,你可以创build一个新的项目(单一的视图应用程序),只需添加导航控制器作为其初始的一个和ViewController类的对象作为其根控制器(只是为了快速获得导航栏)。 下面的代码是我的整个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 } }