Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate add UISearchBar on top of UINavigationBar

If I set the displaysSearchBarInNavigationBar = YES in viewDidLoad, the search bar will be in navigation bar when the view show up. But I want to show search bar on top of navigation bar when I touch bar button item. It's like image below

normal navigation bar: enter image description here

search bar on top of navigation bar after right bar button item clicked enter image description here

like image 831
yong ho Avatar asked Jul 06 '14 07:07

yong ho


2 Answers

I've modified Mark's answer a little to get it to work in IOS 8 and in 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()
  }
}
like image 193
Nick Wargnier Avatar answered Oct 19 '22 09:10

Nick Wargnier


I think the basic idea would be to animate a fade-out of your existing navigation bar's items (leftBarButtonItem(s), titleView, rightBarButtonItem(s)), followed by an animated fade-in of your search bar after it is added as your navigationItem's title view. To revert, animate a fade-out of the search bar, followed by a replacement of your navigationBar's prior items.

The searchBar in the rough example below is stand-alone, but it could also come from elsewhere, like iOS8's new UISearchController. It also assumes that the view controller is embedded in a UINavigationController.

This example builds the UI programmatically, but you should be able to incorporate this approach with a Storyboard-built UI.

The animation that occurs when the user taps the "Cancel" button is a little rough, but hopefully might point the way to a smoother solution.

@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
like image 42
Mark Semsel Avatar answered Oct 19 '22 10:10

Mark Semsel