Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UISearchController SearchBar misaligns while active during rotation

I have been struggling with UISearchController's search bar for quite a while now. I need a search feature to be implemented on a tableview but unlike conventional methods, I didn't put the search bar on a table header view. Instead, I created a UIView and added the search bar as a subview to it. The UIView which acts as a container to search bar has its constraints properly set on the storyboard with auto layout.

Here are my codes for it. Note that I did this programmatically because UISearchDisplayController and UISearchBar has been deprecated as of iOS 8 in favour of UISearchController and has yet to come to UIKit.

searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.autoresizingMask = .FlexibleRightMargin
searchController.searchBar.delegate = self
definesPresentationContext = true
self.searchContainerView.addSubview(searchController.searchBar)

However, I did notice one odd behaviour of the search bar during rotation. When it is active on Portrait, I rotate the simulator to Landscape, and press Cancel, the search bar goes back to Portrait Width.

Effects of activating search in Portrait and then Cancelling in Landscape

The same happens the other way around too.

Effects of activating search in Landscape and then Cancelling in Portrait

I would appreciate any ideas or maybe some hints towards the correct direction to solve this as I have been at this for days at least. Thank you very much

like image 426
Rachel Fong Avatar asked Apr 05 '16 15:04

Rachel Fong


2 Answers

So after so many days of struggling with this:

Portrait to Landscape

  1. Make SearchBar/SearchController active in Portrait
  2. Rotate to Landscape
  3. Press Cancel and SearchBar will go back to Portrait width

Landscape to Potrait

  1. Make SearchBar/SearchController active in Landscape
  2. Rotate to Portrait
  3. Press Cancel and SearchBar will go back to Landscape width

I finally solved it on my own. It seems that when a user presses Cancel on the SearchBar, the ViewController will call viewDidLayoutSubviews thus I tried to reset the width by calling this function in viewDidLayoutSubviews:

func setupSearchBarSize(){
     self.searchController.searchBar.frame.size.width = self.view.frame.size.width
}

But that didn't work as well as I thought. So here is what I think happens. When a user activates the SearchController/SearchBar, the SearchController saves the current frame before it resizes itself. Then when a user presses Cancel or dismisses it, it will use the saved frame and resize to that frame size.

So in order to force its width to be realigned when I press Cancel, I have to implement the UISearchControllerDelegate in my VC and detect when the SearchController is dismissed, and call setupSearchBarSize() again.

Here are the relevant codes to solve this question:

class HomeMainViewController : UIViewController, UISearchControllerDelegate, UISearchResultsUpdating, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
    @IBOutlet weak var searchContainerView: UIView!

override func viewDidLoad() {
    super.viewDidLoad()

        searchController = UISearchController(searchResultsController: nil)
        searchController.searchResultsUpdater = self
        searchController.dimsBackgroundDuringPresentation = false
        searchController.searchBar.autoresizingMask = .FlexibleRightMargin
        searchController.searchBar.delegate = self
        searchController.delegate = self
        definesPresentationContext = true
        self.searchContainerView.addSubview(searchController.searchBar)
        setupSearchBarSize()
}

func setupSearchBarSize(){
        self.searchController.searchBar.frame.size.width = self.view.frame.size.width
}

func didDismissSearchController(searchController: UISearchController) {
        setupSearchBarSize()
}

override func viewDidLayoutSubviews() {
        setupSearchBarSize()
 }
}
like image 107
Rachel Fong Avatar answered Oct 27 '22 15:10

Rachel Fong


Here is simpler solution:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)

        coordinator.animate(alongsideTransition: { (context) in
            self.searchController.searchBar.frame.size.width = self.view.frame.size.width
        }, completion: nil)
    }
like image 42
Dre Sid Avatar answered Oct 27 '22 13:10

Dre Sid