I'm trying to add SearchController to UINavigationBar. I'm trying to set UITextField of UISearchBar after back button of UINavigationController. I want some more space after back button
When I start searching it appears as
Whereas I should be able to view back button. Only textfield width should be decreased. Also after Cancel it should be again back to initial layout. Whereas it is displayed as below:
Below is my code
var searchResultController = UISearchController()
self.searchResultController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
controller.searchBar.delegate = self
controller.hidesNavigationBarDuringPresentation = false
self.navigationController?.navigationBar.addSubview(controller.searchBar)
return controller
})()
override func viewDidAppear(animated: Bool) {
for subView in searchResultController.searchBar.subviews{
for subsubView in subView.subviews {
if let textField = subsubView as? UITextField {
var bounds: CGRect
bounds = textField.frame
bounds.size.width = self.view.bounds.width - 50
}
}
}
}
Please let me know how can I fix this.
Thanks in advance
For setting the UIsearchBar add it to Navigation's titleView as
self.navigationItem.titleView = controller.searchBar
For removing Cancel button we can use UISearchControllerDelegate method
func didPresentSearchController(searchController: UISearchController) {
searchController.searchBar.showsCancelButton = false
}
Hope this may help any one.
Related
I'm trying to attach a search bar to the top of my tableView and change its attributes (eg. colour, placeholder). However, I can't figure out how. I've tried embedding the tableView in another view but that didn't help. Any ideas?
func setupSearch(){
search.delegate = self
search.automaticallyShowsCancelButton = false
search.searchBar.tintColor = UIColor.red
search.searchBar.barTintColor = UIColor.red
search.obscuresBackgroundDuringPresentation = false
search.hidesNavigationBarDuringPresentation = false
search.searchBar.placeholder = "Type something here to search"
navigationItem.searchController = search
tableView.tableHeaderView = search.searchBar
}
This function is called in the viewDidLoad() and the tableView is added but not with the right colour or placeholder and jumps to the top of the screen when selected.
Any help would be appreciated.
This is the updated code for setupSearch (everything is working fine except the bar jumps to the top when selected):
func setupSearch(){
search.delegate = self
search.automaticallyShowsCancelButton = false
search.searchBar.barTintColor = UIColor.red
search.obscuresBackgroundDuringPresentation = false
search.hidesNavigationBarDuringPresentation = false
tableView.tableHeaderView = search.searchBar
}
I declare the search bar at the start using:
let search = UISearchController(searchResultsController: nil)
Any ideas on how to stop the bar jumping to the top?
Just add search bar as tableview's headerview not with navigation's item searchcontroller(not add search bar with both(tableview and navigation) as in your code). You can try with updated code below:
func setupSearch(){
search.delegate = self
search.automaticallyShowsCancelButton = false
search.searchBar.barTintColor = UIColor.red
search.obscuresBackgroundDuringPresentation = false
search.hidesNavigationBarDuringPresentation = false
search.searchBar.placeholder = "Type something here to search"
tableView.tableHeaderView = search.searchBar
self.definesPresentationContext = true
}
override func viewDidLoad() {
super.viewDidLoad()
setupSearch()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) // be notified when the keyboard changes your table View frame
}
#objc func keyboardWillShow(notification: NSNotification) {
tableView.frame.origin.y = 0 // reset the table view to its original coordinates
}
func setupSearch(){
// for iOS 12 and lower, you can change the placeholder like this :
let textFieldSearchBar = searchBar.value(forKey: "searchField") as? UITextField
textFieldSearchBar?.textColor = .red
let searchBarLabel = textFieldSearchBar!.value(forKey: "placeholderLabel") as? UILabel
textFieldSearchBarLabel?.textColor = .red
}
I created a CollectionView. This view has a userProfileImageView and I want to change view controller to ProfilePage when clicked this user profile image. Try some code but neither present nor push view controller doesn't work to me. Can you help me ?
lazy var userProfileImageView: UIImageView = {
let useriv = UIImageView()
useriv.contentMode = .scaleAspectFill
useriv.clipsToBounds = true
useriv.layer.cornerRadius = 40 / 2
useriv.isUserInteractionEnabled = true
useriv.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(userImageTap)))
return useriv
}()
#objc func userImageTap() {
print("useriv clicked")
let profilePage = ProfilePage(collectionViewLayout: UICollectionViewFlowLayout())
}
I have a view controller in my navigation stack that needs to have a transparent navigation bar, while still showing the back button.
I'm able to achieve that with one line of code inside viewWillAppear:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
However, when I try to go back to the previous view, I'm setting the background image back to nil or .none but I'm losing the translucent effect that was previously on there when I do that.
I've tried setting all the following options in viewWillDisappear and none seem to bring the translucency back. It just appears white no matter what I do. The shadow on the bottom is also gone too:
self.navigationController?.navigationBar.isTranslucent = true
self.navigationController?.navigationBar.barStyle = .default
self.navigationController?.navigationBar.backgroundColor = .none
self.navigationController?.navigationBar.setBackgroundImage(.none, for: .default)
Initial Navigation Bar:
Transparent Navigation Bar:
After Transitioning Back:
In viewWillAppear make the navigation bar transparent
override func viewWillAppear(_ animated: Bool) { self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = true
}
And backg to translucent in viewWillDisappear
override func viewWillDisappear(_ animated: Bool) {
self.navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.isTranslucent = false
}
After spending time poking around in the UINavigationBar internals, I did discover a simple method that seems to work, and does not require any configuration of the standard UINavigationBar attributes we've previously fiddled with to achieve transparency. The following is tested working on iOS 12.2.x:
class TallNavigationBar: UINavigationBar {
private lazy var maskingView: UIView = {
let view = UIView(frame: bounds)
view.backgroundColor = .clear
return view
}()
var isTransparent = false {
didSet {
guard isTransparent != oldValue, let bkgView = subviews.first else { return }
bkgView.mask = isTransparent ? maskingView : nil
}
}
}
Obviously, whenever fiddling (even slightly) with undocumented internals: use at your own risk!
This worked for my app which needs to revert to an opaque navigation bar after popping from a transparent navigation bar.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
navigationController?.navigationBar.shadowImage = nil
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.backgroundColor = nil
}
I have a custom UIView that is a subview on a UIViewController.
I have it added in my storyboard and set it to Hidden.
My subview is also within another UIView that I'm using as a 'blur view' which is also initially Hidden.
I have functions that will unhide & hide the subviews.
My custom subview has a UITextField. I can show the keyboard and move the subview up with no problems. When I type in the keyboard or dismiss it my subview moves up and to the left. When I try to show my subview again it shows incorrectly (up and to the left).
The custom subview starts at the center of my screen.
The goal is move it up when the keyboard shows so it will not cover the subview or the UITextField, allow the user to type in the UITextField, and then dismiss the keyboard and move the custom subview back to the center.
In my UIViewController:
// Showing the custom sub view
func displayCustomSubView() {
if let window = UIApplication.shared.keyWindow {
self.blurView.isHidden = false
self.customSubView.isHidden = false
self.blurView.frame = window.frame
self.customSubView.center = window.center
window.addSubview(self.blurView)
UIApplication.shared.keyWindow?.bringSubviewToFront(self.blurView)
}
}
// Hiding the custom sub view
// the custom sub view has a button I tap to hide
#objc func dismissCustomSubView() {
self.blurView.isHidden = true
self.customSubView.isHidden = true
}
// Show Keyboard
// Since I am using the window to make sure my blur view expands to the full frame, I have tried just moving the window up
#objc func keyboardWillShow(sender: NSNotification) {
if let window = UIApplication.shared.keyWindow {
window.frame.origin.y = -75
}
}
// Hide Keyboard
#objc func keyboardWillHide(sender: NSNotification) {
if let window = UIApplication.shared.keyWindow {
window.frame.origin.y = 0
}
}
// Custom Subview Extension
extension CustomSubView: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
Added the Custom Subview Extension above.
First add this notification within your viewDidLoad(). And make a global variable called var keyboardH: CGFloat = 0:
NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardWillShow),
name: UIResponder.keyboardWillShowNotification,
object: nil
)
And this function below:
#objc func keyboardWillShow(_ notification: Notification) {
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
self.keyboardH = keyboardHeight
}
This function is called every time the keyboard is present and will reveal the keyboard height and later we can use this variable.
So in your code:
#objc func keyboardWillShow(sender: NSNotification) {
if let window = UIApplication.shared.keyWindow {
let position = window.frame.origin.y - keyboardH
window.frame.origin.y = position
}
}
Having various problems setting up the UISearchBar to work properly. It should be shown in the navigationBar. Using the "old" way setting navigationItem.titleView = searchController.searchBar. As seen on the picture below, the Cancel button text is truncated. Any ideas how to solve this problem? I have tried to set searchController.searchBar.sizeToFit() with no luck.
fileprivate lazy var searchController: UISearchController = {
let sc = UISearchController(searchResultsController: nil)
sc.delegate = self
sc.searchBar.delegate = self
sc.searchBar.returnKeyType = .done
sc.searchBar.tintColor = UIColor.black
sc.searchResultsUpdater = self
sc.hidesNavigationBarDuringPresentation = false
sc.dimsBackgroundDuringPresentation = false
return sc
} ()