1

I'm attempting to alter the Navigation Bar's narrow shadow bar and am using the following code:

if let hairline = findNavigationBarHairline(navigationBar)
{
    hairline.bounds.size.height = 5.0
    hairline.backgroundColor = UIColor.blueColor()
}

and this:

    func findNavigationBarHairline(view:UIView) -> UIImageView?
    {
        if let hairline = view as? UIImageView where hairline.bounds.size.height <= 1.0
        {
            return hairline
        }
        for subview in view.subviews
        {
            if let imageView = findNavigationBarHairline(subview)
            {
                return imageView
            }
        }
        return nil
    }

This sucessfully finds the UIImageView which is the shadow line but if I try and change anything here it has no effect. Here's a po of the Image View at that point in the code just after its size/color has been set:

(lldb) po hairline
<UIImageView: 0x126d21030; frame = (0 61.75; 320 5); userInteractionEnabled = NO; layer = <CALayer: 0x126d0b470>>

Here it can be seen the height is 5, however it is still displayed with its original size and color. If I use XCode's view hieararchy display and dump the image view from there this is the result:

> Printing description of $124: <UIImageView: 0x126d21030; frame = (0
> 64; 320 0.5); userInteractionEnabled = NO; layer = <CALayer:
> 0x126d0b470>

As can be seen it is the same object, however its height is 0.5 and not 5. Why is the change to the size and color having no effect? (I have also changed the UIImage, but that is not having any effect either).

Gruntcakes
  • 37,738
  • 44
  • 184
  • 378

1 Answers1

0

First - You should do this by setting an image to the shadowImage property of UINavigationBar. That's what that property is for. Note that you have to set a custom background image via setBackgroundImage(_:forBarMetrics:) for this to work. Using the code below I was able to create a white translucent navbar with no shadow. Note that the white image is just a white pixel, which you could easily enough create in code.

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    navigationController!.navigationBar.setBackgroundImage(UIImage(named: "white"), forBarMetrics: .Default)
    navigationController!.navigationBar.shadowImage = UIImage()
}

The result was:

enter image description here

Second - Spelunking into the view hierarchy of components provided by the SDK is generally not the best idea. You've got no guarantees that the view hierarchy won't change in future releases (or that what you've got works on older iOS version, for that matter).

Having said, what you are doing is not working most likely because setting a backgroundColor on an image view isn't going to change the image being rendered by that image view. Second, it's very likely that Apple uses Auto Layout to organize the subviews of UINavigationBar, so the frame/bounds is essentially going to be derived data and Auto Layout will just reset it if you change it.

Charles A.
  • 10,685
  • 1
  • 42
  • 39
  • I know about that approach and have tried but it has complex knock on effects - I'm using a search bar which appears/disappear and other stuff going on and holistically its not working due to the additional requirements to set translucency when using shadowImage. – Gruntcakes Jun 08 '16 at 18:06
  • @ChromiumDioxide I'm working on an app as we speak that uses non-translucent navigation bars with a custom `shadowImage`. Are you certain this is a requirement? – Charles A. Jun 08 '16 at 18:08
  • As I said, changing the UImage also doesn't work, why is that? Changing the size is just to see the results when debugging easier. – Gruntcakes Jun 08 '16 at 18:08
  • @ChromiumDioxide hard to speculate how the internals work. Maybe that `UIImageView` is not the one responsible for the shadow. Maybe `UINavigationBar` aggressively sets the image regularly. – Charles A. Jun 08 '16 at 18:09
  • I was using this as a guide http://stackoverflow.com/questions/19226965/how-to-hide-ios7-uinavigationbar-1px-bottom-line – Gruntcakes Jun 08 '16 at 18:09
  • @ChromiumDioxide I updated my answer with some example code that seems to preserve the translucency. – Charles A. Jun 08 '16 at 19:33