13

I’m attaching a UISearchController to the navigationItem.searchController on iOS 13. This works fine: I can use the nice iOS 13-style search bar.

However, I’d like see the large titles and searchBar by default.

I set navigationItem.hidesSearchBarWhenScrolling = false because I want to see the search permanently on my screen, but the search bar replace large titles by default.

Does anyone know how is this is possible?

Check this out

navigationItem.searchController = UISearchController(searchResultsController: nil)
navigationItem.hidesSearchBarWhenScrolling = false

This is how it looks actually This is how it looks actually

This is how I need to implement(large title and search bar both visible) This is how I need to implement(large title and search bar both visible)

Bonnke
  • 896
  • 1
  • 12
  • 24

4 Answers4

4

For me it worked after adding following lines in the viewDidLoad() method:

searchController.hidesNavigationBarDuringPresentation = true
navigationController?.navigationBar.prefersLargeTitles = true
navigationController!.navigationBar.sizeToFit()
pkamb
  • 33,281
  • 23
  • 160
  • 191
rohit
  • 103
  • 1
  • 7
  • 1
    if you set navigation.navigationBar.sizeToFit(), the searchcontroller gets hidden and only the title is shown. – akaakoz Dec 08 '20 at 08:26
2

I've been trying to achieve the same thing all day long for my app as well and I finally did it.

I wanted to add a searchBar on a UITableViewController and I did it this way.

let searchController: UISearchController = {
    let searchController = UISearchController(searchResultsController: nil)
    
    searchController.searchBar.placeholder = "New Search"
    searchController.searchBar.searchBarStyle = .minimal
    searchController.dimsBackgroundDuringPresentation = false
    searchController.definesPresentationContext = true
    
   return searchController
}()

You first create a new UISearchController using a closure, that way you are able to use it globally in your code and customize it easier in the future.

Afterwards in viewDidLoad, you set the searchSontroller.searchResultsUpdater = self and the navigationItem.searchController = searchController.

For me it works perfectly after a lot of trial and error since I'm doing everything programmatically.

pkamb
  • 33,281
  • 23
  • 160
  • 191
Defkalion1
  • 77
  • 1
  • 12
1

Try this, working fine in my side

    private var search = UISearchController(searchResultsController: nil)

    override func viewDidLoad() {
        super.viewDidLoad()
        search.searchBar.delegate = self
        search.searchBar.sizeToFit()
        search.obscuresBackgroundDuringPresentation = false
        search.hidesNavigationBarDuringPresentation = true
        self.definesPresentationContext = true
        search.searchBar.placeholder = "Search here"
        self.navigationItem.searchController = search
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationItem.hidesSearchBarWhenScrolling = false
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationItem.hidesSearchBarWhenScrolling = true
    }

For large navigation bar use this

For full application navigation bar support please add this extension inside your code.

import UIKit
extension UIViewController {


    open func showNavigationBar(_ large: Bool,
                                _ animated: Bool,
                                titleColor: UIColor,
                                barTintColor: UIColor,
                                fontSize: CGFloat) {

        navigationController?.navigationBar.barTintColor = barTintColor
        navigationController?.navigationBar.backgroundColor = barTintColor
        navigationController?.navigationBar.isTranslucent = true
        self.navigationController?.setNavigationBarHidden(false, animated: animated)
        if large {
            self.navigationController?.navigationBar.prefersLargeTitles = true
            if #available(iOS 13.0, *) {
                let appearance = UINavigationBarAppearance()
                appearance.backgroundColor = barTintColor
                appearance.titleTextAttributes = [.foregroundColor: titleColor]
                appearance.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: titleColor,
                                                       NSAttributedString.Key.font: UIFont(resource: R.font.robotoMedium, size: fontSize)!]

                navigationController?.navigationBar.standardAppearance = appearance
                navigationController?.navigationBar.compactAppearance = appearance
                navigationController?.navigationBar.scrollEdgeAppearance = appearance
            } else {
                self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: titleColor,
                                                                                     NSAttributedString.Key.font: UIFont(resource: R.font.robotoMedium, size: fontSize)!]
            }
        } else {
            self.navigationController?.navigationBar.prefersLargeTitles = false
            self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: titleColor,
                                                                            NSAttributedString.Key.font: UIFont(resource: R.font.robotoMedium, size: 20.0)!]
        }
    }
}

And Then call this method simply

self.showNavigationBar(true, true, titleColor: UIColor.blue, barTintColor: UIColor.red, fontSize: 32.0)

If then Also not work then use this

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        search.searchBar.becomeFirstResponder()
    }

one more solution is that add one UIView with height 0 in storyboard and set-top with safe area and bottom with UIScrollView/UICollectionView/UITableVIew or something else scrollable view and Remove Direct Constraint between TopSafeArea And ScrollableView Top. I know maybe this is not a solution but I did in a storyboard.

Kiran Sarvaiya
  • 1,318
  • 1
  • 13
  • 37
0

This code should work

class NavigationController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()

        createCustomTabBar()
    }

    func createCustomTabBar() {
    
        let firstVC = UINavigationController(rootViewController: HomeVC())
        firstVC.title = "Home"
        firstVC.tabBarItem.image = UIImage(systemName: "house.fill")

        viewControllers = [firstVC]
    }

class HomeVC: UIViewController {
    let searchController = UISearchController(searchResultsController: nil)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        
        navigationController?.navigationBar.prefersLargeTitles = true
        navigationItem.title = "Home"
        navigationItem.searchController = searchController
    }
}

NavigationBar+SearchBar

Alapan Das
  • 17,144
  • 3
  • 29
  • 52
  • From Review:  Code-only answers are discouraged on Stack Overflow because they don't explain how it solves the problem. Please edit your answer to explain what this code does and how it answers the question, so that it is useful to the OP as well as other users also with similar issues. See: [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer). Thanks – sɐunıɔןɐqɐp Sep 03 '20 at 11:44