使用UISearchController同时为UISearchBar和UIBarButtonItem设置动画
我正在尝试重现类似于地图应用的搜索界面。
我在我的navigationBar
使用了一个带有searchBar
的UISearchController
。 我在该导航栏上也有一个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
的解决方案感兴趣。