web-dev-qa-db-fra.com

Comment animer ajouter UISearchBar au-dessus de UINavigationBar

Si je règle le displaysSearchBarInNavigationBar = YES dans viewDidLoad, la barre de recherche sera dans la barre de navigation lorsque la vue apparaîtra. Mais je veux afficher la barre de recherche en haut de la barre de navigation lorsque je touche un élément de bouton de barre. C'est comme l'image ci-dessous

normal barre de navigation: enter image description here

barre de recherche sur en haut de la barre de navigation après avoir cliqué sur l'élément du bouton de la barre de droite enter image description here

42
yong ho

J'ai un peu modifié la réponse de Mark pour le faire fonctionner dans IOS 8 et dans 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()
  }
}
41
Nick Wargnier

Je pense que l'idée de base serait d'animer un fondu sortant des éléments de votre barre de navigation existante (leftBarButtonItem (s), titleView, rightBarButtonItem (s)), suivi d'un fondu animé de votre barre de recherche après son ajout en tant que votre navigation Vue titre de l'objet. Pour revenir en arrière, animez un fondu sortant de la barre de recherche, suivi d'un remplacement des éléments précédents de votre barre de navigation.

La barre de recherche dans l'exemple approximatif ci-dessous est autonome, mais elle pourrait également venir d'ailleurs, comme le nouveau UISearchController d'iOS8. Il suppose également que le contrôleur de vue est intégré dans un UINavigationController.

Cet exemple crée l'interface utilisateur par programme, mais vous devriez être en mesure d'incorporer cette approche à une interface utilisateur créée par Storyboard.

L'animation qui se produit lorsque l'utilisateur appuie sur le bouton "Annuler" est un peu approximative, mais nous espérons qu'elle pourrait indiquer la voie vers une solution plus fluide.

@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
40
Mark Semsel
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.

enter image description hereenter image description here

//  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)")

    }    
}
6
A.G

Je viens de refactoriser la réponse de Nick pour en faire la méthode POP dans Swift 4.

protocol SearchViewAnimateble : class{ }

extension SearchViewAnimateble where Self: UIViewController{

func showSearchBar(searchBar : UISearchBar) {
    searchBar.alpha = 0
    navigationItem.titleView = searchBar
    navigationItem.setRightBarButton(nil, animated: true)

    UIView.animate(withDuration: 0.5, animations: {
        searchBar.alpha = 1
    }, completion: { finished in
        searchBar.becomeFirstResponder()
    })
}

func hideSearchBar( searchBarButtonItem : UIBarButtonItem, titleView : UIView) {
    navigationItem.setRightBarButton(searchBarButtonItem, animated: true)

    titleView.alpha = 0

    UIView.animate(withDuration: 0.3, animations: {
        self.navigationItem.titleView = titleView
        titleView.alpha = 1

    }, completion: { finished in

    })
 }
}

Ensuite, vous pouvez l'utiliser comme ceci

class ViewController : UIViewController, UISearchBarDelegate, SearchViewAnimateble {
 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 = .minimal
    searchBar.showsCancelButton = true

    searchBarButtonItem = navigationItem.rightBarButtonItem
 }

 @IBAction func searchButtonPressed(sender: AnyObject) {
    showSearchBar(searchBar: searchBar)
 }



 //MARK: UISearchBarDelegate
 func searchBarCancelButtonClicked(searchBar: UISearchBar) {

    hideSearchBar( searchBarButtonItem : searchBarButton!, titleView : logoImageView)
  }
}
5
osama