在iOS 11中使用大标题NavigationBar自定义背景图像

ale*_*ner 21 uinavigationbar ios swift ios11

如何在iOS 11中为大型标题NavigationBar设置自定义背景图像?我正在使用我已分配给故事板中的navigationControllers的自定义子类.

这是我创建自定义NavBar的方法:

class CustomNavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        self.navigationBar.tintColor = UIColor(red:1, green:1, blue:1, alpha:0.6)
        self.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
        if #available(iOS 11.0, *) {
            self.navigationBar.prefersLargeTitles = true
            self.navigationItem.largeTitleDisplayMode = .automatic
            self.navigationBar.largeTitleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
            self.navigationBar.barTintColor = UIColor.green
        }
        self.navigationBar.isTranslucent = false
        self.navigationBar.setBackgroundImage(#imageLiteral(resourceName: "navigationBarBackground"), for: .default)
        self.navigationBar.shadowImage = #imageLiteral(resourceName: "navigationBarShadow")
    }
}
Run Code Online (Sandbox Code Playgroud)

奇怪的setBackgroundImage(image, for: .default)是,这对大型游戏不起作用.以前在iOS 10上工作过,如果我旋转iPhone(并激活小型NavBar)背景又回来了吗?

编辑:backgroundImage仍然呈现,但不知隐藏.仅当您开始滚动并出现"普通"导航栏时,才会看到backgroundImage.另外,barTintColor完全是在这种情况下被忽略. 截图 GIF

old*_*dez 18

我有同样的问题,修复它

删除setBackgroundImage并将barTint颜色与模式图像一起使用

let bgimage = imageWithGradient(startColor: UIColor.red, endColor: UIColor.yellow, size: CGSize(width: UIScreen.main.bounds.size.width, height: 1))
self.navigationBar.barTintColor = UIColor(patternImage: bgimage!)
Run Code Online (Sandbox Code Playgroud)

使用渐变颜色获取图像

func imageWithGradient(startColor:UIColor, endColor:UIColor, size:CGSize, horizontally:Bool = true) -> UIImage? {

    let gradientLayer = CAGradientLayer()
    gradientLayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
    gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
    if horizontally {
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
    } else {
        gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0)
        gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
    }

    UIGraphicsBeginImageContext(gradientLayer.bounds.size)
    gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}
Run Code Online (Sandbox Code Playgroud)


Unu*_*nth 7

最后我找到了解决方案!

编辑:适用于 iOS 13 及更高版本


您可以在视图出现之前使用它,例如:在 viewDidLoad() 方法中:

    override func viewDidLoad()
    {
        super.viewDidLoad()

        let largeTitleAppearance = UINavigationBarAppearance() 

        largeTitleAppearance.configureWithOpaqueBackground()
        largeTitleAppearance.backgroundImage = UIImage(named: "BackgroundImage.png")

        self.navigationBar.standardAppearance = largeTitleAppearance
        self.navigationBar.scrollEdgeAppearance = largeTitleAppearance
    }
Run Code Online (Sandbox Code Playgroud)

您只需要:

  1. 创建 UINavigationBarAppearance 实例:

    let largeTitleAppearance = UINavigationBarAppearance() 
    
    Run Code Online (Sandbox Code Playgroud)

    苹果文档:

    UINavigationBarAppearance - 用于自定义导航栏外观的对象。


  1. 配置它:

    largeTitleAppearance.configureWithOpaqueBackground()
    
    Run Code Online (Sandbox Code Playgroud)

    “不透明”在这里是因为我们要设置彩色图像(但实际上没关系,您将设置什么配置)


  1. 设置背景图片:

    largeTitleAppearance.backgroundImage = UIImage(named: "BackgroundImage.png") // Set here image that you need
    
    Run Code Online (Sandbox Code Playgroud)

  1. 将我们的largeTitleAppearance对象分配给standardAppearancescrollEdgeAppearance导航栏的字段:

    self.navigationBar.standardAppearance = largeTitleAppearance // For large-navigationBar condition when it is collapsed
    self.navigationBar.scrollEdgeAppearance = largeTitleAppearance // For large-navigationBar condition when it is expanded
    
    Run Code Online (Sandbox Code Playgroud)

    苹果文档:

    .standardAppearance - 标准高度导航栏的外观设置。

    .scrollEdgeAppearance - 当任何可滚动内容的边缘到达导航栏的匹配边缘时使用的外观设置。


这对我有帮助:https : //sarunw.com/posts/uinavigationbar-changes-in-ios13/#going-back-to-old-style


小智 6

在iOS 11中,如果使用大标题,则无需再设置BackgroundImage(删除其声明)。相反,您需要使用BarTintColor。

class CustomNavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        self.navigationBar.tintColor = UIColor(red:1, green:1, blue:1, alpha:0.6)
        self.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
        if #available(iOS 11.0, *) {
            self.navigationBar.prefersLargeTitles = true
            self.navigationItem.largeTitleDisplayMode = .automatic
            self.navigationBar.largeTitleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
            self.navigationBar.barTintColor = UIColor(red:1, green:1, blue:1, alpha:1)
        }
        else {
            self.navigationBar.setBackgroundImage(#imageLiteral(resourceName: "navigationBarBackground"), for: .default)                
        }
        self.navigationBar.shadowImage = #imageLiteral(resourceName: "navigationBarShadow")
        self.navigationBar.isTranslucent = false
    }
}
Run Code Online (Sandbox Code Playgroud)