user1904273
user1904273

Reputation: 4764

Emulate searchbar in Calendar app

I am trying to emulate the search bar in the Calendar app and finding it surprisingly difficult although many people have posed this question on SO and elsewhere and many half answers have been offered. (I need to support IOS 7).

The main requirements are

1) There is a search bar button.

2) When above button is pressed, a search bar with cancel appears in the navigation bar.

To accomplish 1) you just put a bar button item on the navigation bar. No problem.

To accomplish 2) is the hard part.

To get the search bar to display in the navigation bar as opposed to elsewhere you are supposed to just set self.searchDisplayController.displaysSearchBarInNavigationBar= true as here;

I can get the search bar to appear in the nav bar but without a cancel button.

The code to show a cancel button is supposed to be:

self.searchDisplayController.searchBar.showsCancelButton = YES;

This is not working in conjunction with placing the search bar in the nav bar.

Finally, as opposed to searchDisplayController, something called a search bar has a property called .hidden. After dragging a search bar and search displaycontroller to the view, I've created an outlet property for this and tried to change this without success. (Changing it from true to false has no apparent effect on the output.)

Is there anyone out there who has successfully created this UX who can describe all the steps needed to emulate the search bar in the calendar app in IOS 7.0?

Upvotes: 3

Views: 659

Answers (1)

Florian L.
Florian L.

Reputation: 849

The following code is just to illustrate the idea. If you want to use it, you have to adjust it to your needs, take care for orientation changes and add a tableView. There are also some constants which could be replaced by something better.

class ViewController: UIViewController, UISearchBarDelegate {
    let searchBar = UISearchBar()
    private var searchBarVisible = false

    override func viewDidLoad() {
        super.viewDidLoad()

        searchBar.showsCancelButton = true
        searchBar.delegate = self

        let height: CGFloat = 44
        let window = UIApplication.sharedApplication().keyWindow!
        self.searchBar.frame = CGRectMake(0, -height, window.frame.width, height)
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        self.dismissSearchBarAnimated(true)
    }

    func showSearchBarAnimated(animated: Bool) {
        if !searchBarVisible {
            let window = UIApplication.sharedApplication().keyWindow!
            window.addSubview(searchBar)
            searchBar.setNeedsLayout()
            let duration = animated ? 0.2 : 0 // 0 executes immediately
            self.searchBar.becomeFirstResponder()
            UIView.animateWithDuration(duration) { () -> Void in
                self.searchBar.frame = CGRectMake(0, 20, window.frame.width, self.searchBar.frame.height)
            }
            searchBarVisible = true
        }
    }

    func dismissSearchBarAnimated(animated: Bool) {
        let window = UIApplication.sharedApplication().keyWindow!
        let duration = animated ? 0.2 : 0 // 0 executes immediately
        self.searchBar.resignFirstResponder()
        UIView.animateWithDuration(duration,
            animations: { () -> Void in
                self.searchBar.frame = CGRectMake(0, -self.searchBar.frame.height, window.frame.width, self.searchBar.frame.height)
            }) {(completed) -> Void in
                self.searchBar.removeFromSuperview()
                self.searchBarVisible = false
        }
    }

    @IBAction func actionSearchButton(sender: AnyObject) {
        self.showSearchBarAnimated(true)
    }

    //MARK: - UISearchBarDelegate
    func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
        NSLog("Should search for '\(searchText)'.")
    }

    func searchBarCancelButtonClicked(searchBar: UISearchBar) {
        self.dismissSearchBarAnimated(true)
    }

    func positionForBar(bar: UIBarPositioning) -> UIBarPosition {
        return .TopAttached
    }
}

Upvotes: 4

Related Questions