Изменение границы нижней границы панели навигации Swift

Он работает с

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
    self.navigationController?.navigationBar.shadowImage = UIColor.redColor().as1ptImage()


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

extension UIColor {
    func as1ptImage() -> UIImage {
        UIGraphicsBeginImageContext(CGSizeMake(1, 1))
        let ctx = UIGraphicsGetCurrentContext()
        self.setFill()
        CGContextFillRect(ctx, CGRect(x: 0, y: 0, width: 1, height: 1))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

Но когда я добавляю UITableView, он не появляется на нем, и когда я добавляю UISearchView, он появляется, но удаляет панель навигации.

Кто-нибудь знает, как это решить?

Ответ 1

Вам нужно настроить свойство shadowImage на панели навигации.

Попробуйте это. Я создал категорию на UIColor в качестве помощника, но вы можете реорганизовать то, как вы предпочитаете.

extension UIColor {
    func as1ptImage() -> UIImage {
        UIGraphicsBeginImageContext(CGSizeMake(1, 1))
        let ctx = UIGraphicsGetCurrentContext()
        self.setFill()
        CGContextFillRect(ctx, CGRect(x: 0, y: 0, width: 1, height: 1))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

Вариант 1: на одной навигационной панели

И затем в вашем представлении контроллер (измените UIColor на то, что вам нравится):

// We can use a 1px image with the color we want for the shadow image
self.navigationController?.navigationBar.shadowImage = UIColor.redColor().as1ptImage()

// We need to replace the navigation bar background image as well 
// in order to make the shadowImage appear. We use the same 1px color tecnique
self.navigationController?.navigationBar.setBackgroundImage(UIColor.yellowColor‌​().as1ptImage(), forBarMetrics: .Default)    

Вариант 2: использование внешнего прокси-сервера, на всех навигационных панелях

Вместо того, чтобы устанавливать фоновое изображение и теневое изображение на каждой панели навигации, можно полагаться на прокси-сервер UIAppearance. Вы можете попытаться добавить эти строки в AppDelegate вместо добавления предыдущих в viewDidLoad.

// We can use a 1px image with the color we want for the shadow image
UINavigationBar.appearance().shadowImage = UIColor.redColor().as1ptImage()

// We need to replace the navigation bar background image as well 
// in order to make the shadowImage appear. We use the same 1px color technique
UINavigationBar.appearance().setBackgroundImage(UIColor.yellowColor().as1ptImage(), forBarMetrics: .Default)

Ответ 2

Замечательные вклады от @TheoF, @Alessandro и @Pavel.

Вот что я сделал для...

Swift 4

extension UIColor {

    /// Converts this `UIColor` instance to a 1x1 `UIImage` instance and returns it.
    ///
    /// - Returns: `self` as a 1x1 `UIImage`.
    func as1ptImage() -> UIImage {
        UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
        setFill()
        UIGraphicsGetCurrentContext()?.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
        let image = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
        UIGraphicsEndImageContext()
        return image
    }
}

Используя его в viewDidLoad():

/* In this example, I have a ViewController embedded in a NavigationController in IB. */

// Remove the background color.
navigationController?.navigationBar.setBackgroundImage(UIColor.clear.as1ptImage(), for: .default)

// Set the shadow color.
navigationController?.navigationBar.shadowImage = UIColor.gray.as1ptImage()

Ответ 3

для Swift 3.0 просто измените эту строку:

CGContextFillRect(ctx, CGRect(x: 0, y: 0, width: 1, height: 1))

:

ctx?.fill(CGRect(x: 0, y: 0, width: 1, height: 1))

Ответ 4

Помещение ответа @alessandro-orru в одно расширение

extension UINavigationController {

    func setNavigationBarBorderColor(_ color:UIColor) {
        self.navigationBar.shadowImage = color.as1ptImage()
    }
}

extension UIColor {

    /// Converts this 'UIColor' instance to a 1x1 'UIImage' instance and returns it.
    ///
    /// - Returns: 'self' as a 1x1 'UIImage'.
    func as1ptImage() -> UIImage {
        UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
        setFill()
        UIGraphicsGetCurrentContext()?.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
        let image = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
        UIGraphicsEndImageContext()
        return image
    }
}

тогда в вашем контроллере представления просто добавьте:

self.navigationController?.setNavigationBarBorderColor(UIColor.red)

Ответ 5

Начиная с iOS 13, вы можете использовать класс UINavigationBarAppearance() со свойством shadowColor:

if #available(iOS 13.0, *) {
  let style = UINavigationBarAppearance()
  style.shadowColor = UIColor.clear // Effectively removes the border
  navigationController?.navigationBar.standardAppearance = style

  // Optional info for follow-ups:
  // The above will override other navigation bar properties so you may have to assign them here, for example:
  //style.buttonAppearance.normal.titleTextAttributes = [.font: UIFont(name: "YourFontName", size: 17)!]
  //style.backgroundColor = UIColor.orange
  //style.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white,
                               NSAttributedString.Key.font: UIFont(name: "AnotherFontName", size: 20.0)!]
} else {
  // Fallback on earlier versions
}