使用UISearchController同时为UISearchBar和UIBarButtonItem设置动画

我正在尝试重现类似于地图应用的搜索界面。

我在我的navigationBar使用了一个带有searchBarUISearchController 。 我在该导航栏上也有一个rightBarButtonItem

默认情况下,在显示搜索控制器时,搜索栏的取消按钮显示在现有的右侧项目旁边。 我想做的事情 – 比如使用地图应用程序 – 是在显示searchController时隐藏我的右侧导航项,并在它被解除时再次显示它。

我已经设法使用委托方法来完成它,但是动画中有一个非常难看的跳转,我想知道如何避免这种情况。

这是我的代码(右边的条形项将切换慢动画,使bug更容易看到)

AppDelegate.h

 // // AppDelegate.h // SearchNavigationItemAnimation // #import  @interface AppDelegate : UIResponder  @property (strong, nonatomic) UIWindow *window; @end 

AppDelegate.m

 // // AppDelegate.m // SearchNavigationItemAnimation // #import "AppDelegate.h" #import "SearchViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; SearchViewController *rootController = [[SearchViewController alloc] init]; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootController]; self.window.rootViewController = navigationController; [self.window makeKeyAndVisible]; return YES; } @end 

SearchViewController.h

 // // SearchViewController.h // SearchNavigationItemAnimation // #import  @interface SearchViewController : UIViewController @end 

SearchViewController.m

 // // SearchViewController.m // SearchNavigationItemAnimation // #import "SearchViewController.h" @interface SearchViewController ()  @property (nonatomic, strong) UISearchController *searchController; @property (nonatomic, strong) UIBarButtonItem *rightBarButtonItem; @end @implementation SearchViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor lightGrayColor]; self.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:self action:@selector(navigationBarButtonItemAction)]; UITableViewController *searchResultsController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain]; self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController]; self.searchController.delegate = self; self.searchController.searchResultsUpdater = self; self.searchController.hidesNavigationBarDuringPresentation = NO; self.navigationItem.titleView = self.searchController.searchBar; self.navigationItem.rightBarButtonItem = self.rightBarButtonItem; self.definesPresentationContext = YES; } - (void)willPresentSearchController:(UISearchController *)searchController { [self.navigationItem setRightBarButtonItem:nil animated:true]; } - (void)willDismissSearchController:(UISearchController *)searchController { [self.navigationItem setRightBarButtonItem:self.rightBarButtonItem animated:true]; } - (void)navigationBarButtonItemAction { float windowLayerSpeed = [UIApplication sharedApplication].keyWindow.layer.speed; [UIApplication sharedApplication].keyWindow.layer.speed = (windowLayerSpeed == 1.0) ? 0.1 : 1.0; } - (void)updateSearchResultsForSearchController:(UISearchController *)searchController { } @end 

编辑

让我再解释一下发生了什么。

如果没有添加barButtonItem,则searchBar将占用导航栏的整个宽度。 当你触摸它时,它会激活并显示取消按钮并带有一个漂亮的动画(搜索字段会缩小,从右边滑入的取消按钮会留下空间)。

使用导航栏上的右键,如果您不尝试添加/删除/以任何方式修改它,它的工作方式相同。 搜索栏占据除按钮宽度以外的所有空间,当它激活时,取消按钮从按钮的右侧和下方滑入,并在其旁边(在搜索区域和现有的右侧按钮之间)。 一切都是动画的,工作正常。

现在,如果要在取消按钮滑动时使右按钮消失,则必须为其框架设置动画。 问题是搜索栏会自动尝试占用所有可用空间,并且不会为其框架设置动画。 因此,我们假设您想要将按钮的帧宽设置为零,搜索栏将立即扩展其宽度而不是跟随您的动画。

这显然是一个错误,或者如果你更宽容一个尚未实现的function ……但它在iOS7中使用UISearchDisplayController工作正常,Apple在地图应用程序中完成。 所以我要求任何可行的解决方法,包括必要时的私有API调用。

如果有人感兴趣,我设法使用UISearchDisplayController使其工作。 请参阅此示例项目 。

我仍然对可以使用UISearchController的解决方案感兴趣。