如何animation在UINavigationBar顶部添加UISearchBar

如果我在viewDidLoad设置了displaysSearchBarInNavigationBar = YES ,当视图显示时,search栏将在导航栏中。 但是,当我触摸栏button项目时,我想在导航栏顶部显示search栏。 这就像下面的图片

正常的导航栏: 在这里输入图像说明

在点击右键栏button项之后,导航栏顶部的search栏 在这里输入图像说明

我认为最基本的想法是animation淡出现有的导航条的项目(leftBarButtonItem(s),titleView,rightBarButtonItem(s)),然后在添加你的search栏的animation淡入作为你的navigationItem的标题视图。 恢复,animation淡出search栏,然后replace您的navigationBar的先前的项目。

下面粗略的例子中的searchBar是独立的,但也可能来自其他地方,比如iOS8的新的UISearchController。 它还假定视图控制器embedded在UINavigationController中。

本示例以编程方式构buildUI,但您应该可以将此方法与Storyboard构build的UI结合使用。

当用户点击“取消”button时发生的animation有点粗糙,但希望能指出一个更顺利的解决scheme。

 @interface ViewController() <UISearchBarDelegate> @property (nonatomic, strong) UIButton *searchButton; @property (nonatomic, strong) UIBarButtonItem *searchItem; @property (nonatomic, strong) UISearchBar *searchBar; @end - (void)viewDidLoad { [super viewDidLoad]; // create the magnifying glass button self.searchButton = [[UIButton alloc] init]; // add button images, etc. [_searchButton addTarget:self action:@selector(searchButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; self.searchItem = [[UIBarButtonItem alloc] initWithCustomView:_searchButton]; self.navigationItem.rightBarButtonItem = _searchItem; self.searchBar = [[UISearchBar alloc] init]; _searchBar.showsCancelButton = YES; _searchBar.delegate = self; } - (void)searchButtonTapped:(id)sender { [UIView animateWithDuration:0.5 animations:^{ _searchButton.alpha = 0.0f; } completion:^(BOOL finished) { // remove the search button self.navigationItem.rightBarButtonItem = nil; // add the search bar (which will start out hidden). self.navigationItem.titleView = _searchBar; _searchBar.alpha = 0.0; [UIView animateWithDuration:0.5 animations:^{ _searchBar.alpha = 1.0; } completion:^(BOOL finished) { [_searchBar becomeFirstResponder]; }]; }]; } #pragma mark UISearchBarDelegate methods - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { [UIView animateWithDuration:0.5f animations:^{ _searchBar.alpha = 0.0; } completion:^(BOOL finished) { self.navigationItem.titleView = nil; self.navigationItem.rightBarButtonItem = _searchItem; _searchButton.alpha = 0.0; // set this *after* adding it back [UIView animateWithDuration:0.5f animations:^ { _searchButton.alpha = 1.0; }]; }]; }// called when cancel button pressed 

我已经稍微修改了Mark的答案,以便在IOS 8和Swift中工作。

 class ViewController : UIViewController, UISearchBarDelegate { var searchBar = UISearchBar() var searchBarButtonItem: UIBarButtonItem? var logoImageView : UIImageView! override func viewDidLoad() { super.viewDidLoad() // Can replace logoImageView for titleLabel of navbar let logoImage = UIImage(named: "logo-navbar")! logoImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: logoImage.size.width, height: logoImage.size.height)) logoImageView.image = logoImage navigationItem.titleView = logoImageView searchBar.delegate = self searchBar.searchBarStyle = UISearchBarStyle.Minimal searchBarButtonItem = navigationItem.rightBarButtonItem } @IBAction func searchButtonPressed(sender: AnyObject) { showSearchBar() } func showSearchBar() { searchBar.alpha = 0 navigationItem.titleView = searchBar navigationItem.setLeftBarButtonItem(nil, animated: true) UIView.animateWithDuration(0.5, animations: { self.searchBar.alpha = 1 }, completion: { finished in self.searchBar.becomeFirstResponder() }) } func hideSearchBar() { navigationItem.setLeftBarButtonItem(searchBarButtonItem, animated: true) logoImageView.alpha = 0 UIView.animateWithDuration(0.3, animations: { self.navigationItem.titleView = self.logoImageView self.logoImageView.alpha = 1 }, completion: { finished in }) } //MARK: UISearchBarDelegate func searchBarCancelButtonClicked(searchBar: UISearchBar) { hideSearchBar() } } 
 Following Nick's answer, I made a similar one on Xcode 7.1 -swift 2.0. Note: To the Navigation Bar, I added (a) UIBarButtons( Drag& Drop) - menuButton & searchButton (b) UIBarButtons (programatically) - leftSearchBarButtonItem & rightSearchBarButtonItem. The common methods are : (a) showSearchBar(), hideSearchBar() (b) revealToggle: - It is connected to SWRevealController for Slider Menu. 

在这里输入图像说明 在这里输入图像说明

 // DashBoardViewController.swift import UIKit class DashBoardViewController: UIViewController,UISearchBarDelegate,SWRevealViewControllerDelegate { //MARK:- STORYBOARD REFERENCE @IBOutlet weak var menuButton: UIBarButtonItem! @IBOutlet weak var searchButtton: UIBarButtonItem! //Making secondary Searchbar var searchBar = UISearchBar() var leftSearchBarButtonItem: UIBarButtonItem? var rightSearchBarButtonItem: UIBarButtonItem? var logoImageView : UIImageView! override func viewDidLoad() { super.viewDidLoad() self.activateInitialUISetUp() // self.revealViewController().delegate = self makeTopNavigationSearchbar() } override func viewWillAppear(animated: Bool) { makeTopNavigationSearchbar() activateInitialUISetUp() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } //MARK:- SEARCHBAR METHODS func searchBarSearchButtonClicked(searchBar: UISearchBar) { hideSearchBar() searchBar.resignFirstResponder() } func searchBarTextDidBeginEditing(searchBar: UISearchBar) { } func searchBarCancelButtonClicked(searchBar: UISearchBar) { hideSearchBar() } //Search Bar Appear & Disappear func showSearchBar() { searchBar.hidden = false searchBar.alpha = 0 navigationItem.titleView = searchBar navigationItem.setLeftBarButtonItem(nil, animated: true) navigationItem.setRightBarButtonItem(nil, animated: true) UIView.animateWithDuration(0.5, animations: { self.searchBar.alpha = 1 }, completion: { finished in self.searchBar.becomeFirstResponder() }) } func hideSearchBar() { hideSearchBarAndMakeUIChanges() logoImageView.alpha = 0 UIView.animateWithDuration(0.3, animations: { self.logoImageView.alpha = 1 }, completion: { finished in }) } //Making secondary Searchbar func makeTopNavigationSearchbar() { let logoImage = UIImage(named: "password")! logoImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: logoImage.size.width, height: logoImage.size.height)) logoImageView.image = logoImage searchButtton.customView?.addSubview(logoImageView) searchBar.delegate = self searchBar.searchBarStyle = UISearchBarStyle.Minimal leftSearchBarButtonItem = navigationItem.leftBarButtonItem rightSearchBarButtonItem = navigationItem.rightBarButtonItem leftSearchBarButtonItem?.tintColor = UIColor.whiteColor() rightSearchBarButtonItem?.tintColor = UIColor.whiteColor() } //Adding secondary uibar butttons to navigation bar func hideSearchBarAndMakeUIChanges () { searchBar.hidden = true //Adding secondary uibarbuttons to the nav bar and revoke its methods navigationItem.setLeftBarButtonItem(leftSearchBarButtonItem, animated: true) navigationItem.setRightBarButtonItem(rightSearchBarButtonItem, animated: true) leftSearchBarButtonItem?.title = "Menu" leftSearchBarButtonItem?.target = self.revealViewController() leftSearchBarButtonItem?.action = "revealToggle:" rightSearchBarButtonItem?.title = "Search" rightSearchBarButtonItem?.target = self rightSearchBarButtonItem?.action = "showSearchBar" //Adding Title Label var navigationTitlelabel = UILabel(frame: CGRectMake(0, 0, 200, 21)) navigationTitlelabel.center = CGPointMake(160, 284) navigationTitlelabel.textAlignment = NSTextAlignment.Center navigationTitlelabel.textColor = UIColor.whiteColor() navigationTitlelabel.text = "WORK ORDER" self.navigationController!.navigationBar.topItem!.titleView = navigationTitlelabel } //UI-Related Methods func activateInitialUISetUp() { self.navigationController?.navigationBarHidden = false self.navigationController?.navigationBar.barStyle = UIBarStyle.BlackOpaque self.navigationController?.navigationBar.translucent = true self.navigationController?.navigationBar.backgroundColor = UIColor.redColor() //Nav Bar Searchbar searchBar.delegate = self searchBar.placeholder = "Start Your Search Here" searchButtton.action = "showSearchBar" searchButtton.target = self //searchbar Text Color var textFieldInsideSearchBar = searchBar.valueForKey("searchField") as? UITextField textFieldInsideSearchBar?.textColor = UIColor.whiteColor() //Nav Bar Title self.title = "WORK ORDER" if self.revealViewController() != nil { menuButton.target = self.revealViewController() menuButton.action = "revealToggle:" self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer()) self.revealViewController().rearViewRevealWidth = self.view.frame.width / 2 self.revealViewController().rearViewRevealOverdraw = 0.0 self.view.addGestureRecognizer(self.revealViewController().tapGestureRecognizer()) } } func revealController(revealController: SWRevealViewController!, didMoveToPosition position: FrontViewPosition) { if(position.rawValue == 3) { } else { } print("position\(position)") } }