I'm presenting a UISearchController
from my controller embedded in a navigation controller. The default animation occurs, where the search box drops down from the top on the navigation bar.
This isn't a good UX in my case because I present the search when a user taps into a UITextField
in the middle of the screen. What I'd like to do is have the UITextField
float to the top and morph into the search box, but I can't figure how to do this.
This is what I have:
class PlacesSearchController: UISearchController, UISearchBarDelegate {
convenience init(delegate: PlacesAutocompleteViewControllerDelegate) {
let tableViewController = PlacesAutocompleteContainer(
delegate: delegate
)
self.init(searchResultsController: tableViewController)
self.searchResultsUpdater = tableViewController
self.hidesNavigationBarDuringPresentation = false
self.definesPresentationContext = true
self.searchBar.placeholder = searchBarPlaceholder
}
}
private extension ShowAddressViewController {
@objc func streetAddressTextFieldEditingDidBegin() {
present(placesSearchController, animated: true, completion: nil)
}
}
Instead of the search dropping down from the top, I'm hoping to get the text field fly up to the nav bar. What I’m after is the same effect that’s on the iOS 11 File app:
It has a text field in the middle of the screen then animated up to the navigation bar when you tap on it. In my case though, the text field is way lower in the screen and not originally part of the navigation bar.
UISearchController is a component that highly difficult to customize. From my experience I can say, that it is better to use it as is without any drastic or significant customization. Otherwise, customization could result in messy code, global state variables, runtime tricks with UIView hierarchy etc. If specific behavior still needed, it is better to implement search controller from scratch or use third party one.
Looks like UISearchController was designed to be used in couple with UITableView and UISearchBar installed in the table header view. Even apple official code samples and documentation provides such example of usage (see UISearchController). Attempt to install UISearchBar somewhere else often results in numerous ugly side effects with search bar frame, position, twitching animations, orientation changes etc.
Starting with iOS 11, UINavigationItem got searchController property. It allows to integrate search controller into your navigation interface, so search will look exactly like iOS Files or iOS AppStore app. UISearchController's behavior still coupled with another component, but I believe it is better than coupling with UITableView all the time.
From my perspective there are several possible solutions for your problem. I will provide them in order of increasing effort, which is needed for implementation:
I hope this helps.
Update:
I have implemented approach I described under point 3. Here is how it works:
You can find code snippet here. Please note, that it is only code example, there are might be situations which are not handled. Check it twice then.
Add UIButton inside above UIView in same xib and name it btnSearch. Like below 
Setup search controller in ViewDidLoad as below:
func setupSearchController() {
self.searchController = UISearchController(searchResultsController: nil)
self.searchController.delegate = self
self.searchController.searchBar.delegate = self
definesPresentationContext = true
self.searchController.dimsBackgroundDuringPresentation = false
self.searchController.searchBar.sizeToFit()
searchView.addSubview(self.searchController.searchBar)
self.searchController.searchBar.isHidden = true
self.searchController.searchBar.tintColor = UIColor.white
self.searchController.searchBar.showsCancelButton = false
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = session?.makeColor(fromHexString: TYPE_COLOR, alpha: 1.0)
self.searchController.searchBar.isTranslucent = false
self.searchController.searchBar.barTintColor = UIColor(red: 239.0 / 255.0, green: 135.0 / 255.0, blue: 1.0 / 255.0, alpha: 1.0)
}
This method will setup searchcontroller programatically inside searchview.
Now you just need to show searchcontroller programatically. add On click method of button in step 2. Call this below method name showsearchAnimation:
func ShowSeachAnimation() {
searchFrame = searchView.frame (add one global variable "searchFrame" in controller which saves searchView.frame so it will be used when cancel button clicked on search)
self.btnSearch.isHidden = true
var yAxis : CGFloat = 20
if #available(iOS 11 , *) {
yAxis = 8
} else {
yAxis = 20
}
searchView.translatesAutoresizingMaskIntoConstraints = true
searchView.frame = CGRect(x: 0, y: yAxis, width: view.frame.size.width, height: view.frame.size.height - yAxis)
self.searchController.searchBar.isHidden = false
self.searchController.searchBar.becomeFirstResponder()
self.searchController.searchBar.showsCancelButton = true
self.searchBar(self.searchController.searchBar, textDidChange: "")
searchView.layoutIfNeeded()
}
For hide searchbar, Add search hide method named "searchbarcancelbuttonclicked" in searchcontroller delegate:
func searchViewHideAnimation() {
self.removeNavigationBar()
self.navigationController?.isNavigationBarHidden = false
self.searchController.searchBar.text = " "
self.searchController.searchBar.isHidden = true
UIView.animate(withDuration: 0.3, animations: {() -> Void in
self.searchView.frame = self.searchFrame!
self.btnSearch.isHidden = false
}, completion: {(_ finished: Bool) -> Void in
self.searchView.layoutIfNeeded()
})
}
you can try to use my https://github.com/Blackjacx/SHSearchBar Which essentially will be your text field. You can add constraints to the left, right and top and adjust the top constraint when the text field editing begins. At the same time, you hide the navigation bar animated and gray out the background by using an overlay view. This way you have maximized control over your animations and this appüroach is not so difficult as it might sound.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With