13

I read many threads, but none solved this question in a clear, consistent answer for the latest version of Swift.

For example, this question's top answer suggests UINavigationBar.appearance().setShadowImage(). However, such a method does not exist in the latest version of swift.

I don't want to hide the bottom border. I just want to change the color.

Additionally, it'd be great to be able to change the height, but I know I'm asking too much in one question.

Edit: I created a 2x1 pixel image and set it to the shadowImage, but the border remains unchanged:

UINavigationBar.appearance().barTintColor = UIColor.whiteColor()
UINavigationBar.appearance().shadowImage = UIImage(named: "border.jpg") //in my AppDelegate, for global appearance

Here's the image; it's really small: border image

Community
  • 1
  • 1
TIMEX
  • 259,804
  • 351
  • 777
  • 1,080

3 Answers3

23

SWIFT 2.x :

Out of convenience, I've extended UIImage() to allow me to essentially use it as a color with the code immediately below.

extension UIImage {
    class func imageWithColor(color: UIColor) -> UIImage {
        let rect = CGRectMake(0, 0, 1.0, 0.5)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
        color.setFill()
        UIRectFill(rect)
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

Next, you'll want to add the following lines to your code to adjust the viewController's UINavigationBar's shadow image, or color in this instance.

// Sets Bar's Background Image (Color) //
self.navigationController?.navigationBar.setBackgroundImage(UIImage.imageWithColor(UIColor.blueColor()), forBarMetrics: .Default)
// Sets Bar's Shadow Image (Color) //
self.navigationController?.navigationBar.shadowImage = UIImage.imageWithColor(UIColor.redColor())

SWIFT 3.x / 4.x :

Extension code:

extension UIImage {
    class func imageWithColor(color: UIColor) -> UIImage {
        let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 0.5)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
        color.setFill()
        UIRectFill(rect)
        let image : UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }
}

NavigationBar code:

// Sets Bar's Background Image (Color) //
navigationController?.navigationBar.setBackgroundImage(UIImage.imageWithColor(color: .blue), for: .default)
// Sets Bar's Shadow Image (Color) //
navigationController?.navigationBar.shadowImage = UIImage.imageWithColor(color: .red)

Edit 1:

Updated extension code so you can adjust rect size without changing UIImage color opacity.

Edit 2:

Added Swift 3 + Swift 4 code.

ZGski
  • 2,398
  • 1
  • 21
  • 34
  • Do you know , why I change the height/width of your rect to ```0.5```, the color changes? – TIMEX May 16 '16 at 21:18
  • @TIMEX, I've update my code so this shouldn't happen anymore – ZGski May 16 '16 at 22:26
  • this definitely works but the shadow image on every view controller inside my app all get the color change. – Lance Samaria Mar 10 '19 at 12:54
  • @LanceSamaria You'll need to reset the `navigationBar` properties for the `ViewController`s that you don't want to take on the new look because the `NavigationController` is a single instance that contains children `ViewControllers`. – ZGski Mar 11 '19 at 15:54
2

Old UIKit setter methods like UISomeClass.setSomething(whatIWantToSet) have been reformulated so that you can directly set them with an = sign. So, in my example you would have to use UISomeClass.something = whatIWantToSet.

In your case, it's UINavigationBar.appearance().shadowImage = whatYouWantToSet.

catalandres
  • 1,149
  • 8
  • 20
0

A bit tricky solution, but it works with no coding and extensions needed. Just add in StoryBoard under your navigationBar a Progress View and set its color and height to whatever you like. If you want full border also set progress to 1.

enter image description here

So you will get a proper border for your navigation bar and an option to add progressView at any time as extra bonus. I know, I know... it's kinda tricky, but programmers should be lazy, no?

Shalugin
  • 1,092
  • 2
  • 10
  • 15