Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove shadow below UINavigationBar with UISearchController

Tags:

ios

swift

Image 1

I could successfully remove the shadow below the navigation bar with the following line of code.

self.navigationController?.navigationBar.shadowImage = UIImage()

Image 2

When I added a search controller however, the shadow reappeared.

self.navigationItem.searchController = UISearchController(searchResultsController: nil)

Image 3

I tried the following, but resulted an unexpected behavior.

self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.barTintColor = .white
self.navigationController?.navigationBar.isTranslucent = false

Image 4

How do I remove the shadow under a navigation bar when there is a search controller attached?

like image 222
Affinity Avatar asked Jan 08 '18 11:01

Affinity


2 Answers

I have not found good solution too...

for now I will hide it this way:

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        if let imageView = navigationItem.searchController?.searchBar.superview?.subviews.first?.subviews.first as? UIImageView {
            imageView.isHidden = true
        }
    }
like image 57
Kirow Avatar answered Oct 17 '22 18:10

Kirow


Here's the solution that I use

  1. Create a separate class extending a UINavigationController instance, lets call it BaseNavigationController. Here's your class for you

  2. If you are using storyboards, assign BaseNavigationController to your UINavigationController scene in the storyboard

  3. If you are initializing a navigation controller via code, ex: UINavigationController.init(rootViewController: someViewControllerInstance) then simply use BaseNavigationController.init(rootViewController: someViewControllerInstance)

An example of the class is shown below:

open class BaseNavigationController:UINavigationController {

    override open func viewDidLoad() {
        super.viewDidLoad()
        setNavigationBar()
        setNavBarBorder(false)
    }

    func setNavigationBar(color:UIColor?=UIColor.white, tint:UIColor?=UIColor.darkGray){
        let appearance = UIBarButtonItem.appearance()
        appearance.setBackButtonTitlePositionAdjustment(UIOffset.init(horizontal: 0.0, vertical: 0), for: .default)
        self.navigationBar.barTintColor = color!
        self.navigationBar.isTranslucent = false
        self.navigationBar.tintColor = tint!
        self.navigationBar.titleTextAttributes = [ NSAttributedString.Key.foregroundColor: tint! ]
    }

    func setTitleColor(_ color:UIColor?=UIColor.darkGray){

    }

    func setNavBarBorder(_ enable:Bool) {
        self.navigationBar.setBackgroundImage((enable ? nil : UIImage()), for: UIBarMetrics.default)
        self.navigationBar.shadowImage = (enable ? nil : UIImage())
        self.navigationBar.setValue(true, forKey: "hidesShadow")
    }

}

Now, the fun part, if you are handling ambiguous layout you might need to do this in viewWillLayoutSubviews otherwise putting this bit of code in viewWillAppear of the viewController instance.

(self.navigationController as? BaseNavigationController)?. setNavBarBorder(false)

the interesting bit of code is in self.navigationBar.setValue(true, forKey: "hidesShadow"), for some versions of iOS.

like image 32
Kinshuk Kashyap Avatar answered Oct 17 '22 18:10

Kinshuk Kashyap