iOS 11 中带有大标题导航栏的自定义背景图片
custom background image with large titles NavigationBar in iOS 11
iOS11如何为大标题NavigationBar设置自定义背景图片?我正在使用自定义子类,我已将其分配给情节提要中的 navigationControllers。
这就是我创建自定义导航栏的方式:
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")
}
}
奇怪的是,setBackgroundImage(image, for: .default)
不适用于大标题。它以前与 iOS 10 一起工作,如果我旋转 iPhone(并激活小导航栏)背景又回来了?
编辑:
backgroundImage
仍然呈现但不知何故被隐藏了。只有当您开始滚动并且 "normal" 导航栏出现时,背景图像才可见。在这种情况下, barTintColor
也被完全忽略。
在 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
}
}
我遇到了同样的问题,已由
修复
删除 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!)
获取具有渐变颜色的图像
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
}
在 Xamarin 中它会是这样的:
this.NavigationBar.BackgroundColor = UIColor.Clear;
var gradientLayer = new CAGradientLayer
{
Frame = new CGRect(0, 0, UIApplication.SharedApplication.StatusBarFrame.Width,
UIApplication.SharedApplication.StatusBarFrame.Height + this.NavigationBar.Frame.Height),
Colors = new CGColor[]
{Constants.Defaults.Navigation.RealBlueColor.ToCGColor(), Constants.Defaults.Navigation.RealBlueColor.ToCGColor()}
};
UIGraphics.BeginImageContext(gradientLayer.Bounds.Size);
gradientLayer.RenderInContext((UIGraphics.GetCurrentContext()));
UIImage image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
this.View.Layer.InsertSublayer(gradientLayer, 0);
this.NavigationBar.BarTintColor = UIColor.FromPatternImage(image);
this.View.Layer.Insert可选。当我 "curling" 在 NavigationBar
上上下移动图像时我需要它
试试这个代码 (Swift 4.0):
在viewDidLoad()中
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.black]
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
self.navigationItem.largeTitleDisplayMode = .automatic
self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.black]
} else {
//iOS <11.0
}
self.title = "Title"
self.navigationController?.navigationBar.barTintColor = UIColor(patternImage: #imageLiteral(resourceName: "nav_bg"))
self.navigationController?.navigationBar.isTranslucent = false
借用 oldrinmendez 的回答 - 该解决方案非常适合水平渐变。
对于垂直渐变,我能够通过在 scrollViewDidScroll 中再次调用它来使用 oldrinmendez 的答案中的相同函数。这会在用户滚动时不断调整渐变图像的高度。
从 oldrinmendez 的函数开始:
func imageWithGradient(startColor:UIColor, endColor:UIColor, size:CGSize, horizontally:Bool) -> 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)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
}
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
创建一个更新函数以使用您想要的选项调用它:
func updateImageWithGradient() {
let navBarHeight = self.navigationController?.navigationBar.frame.size.height
let statusBarHeight = UIApplication.shared.statusBarFrame.height
let heightAdjustment: CGFloat = 2
let gradientHeight = navBarHeight! + statusBarHeight + heightAdjustment
let bgimage = imageWithGradient(startColor: UIColor.red, endColor: UIColor.orange, size: CGSize(width: UIScreen.main.bounds.size.width, height: gradientHeight), horizontally: false)
navigationController?.navigationBar.barTintColor = UIColor(patternImage: bgimage!)
}
最后给 scrollViewDidScroll & ViewDidApper 添加更新函数: 使用 ViewDidAppear 返回正确的导航栏高度
override func viewDidAppear(_ animated: Bool) {
updateImageWithGradient()
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
DispatchQueue.main.async {
updateImageWithGradient()
}
}
更改 barTint 对我不起作用,所以我更改了 navigationBar 中的图层
navigationBar.layer.backgroundColor = UIColor(patternImage:
UIImage(named: "BG-Roof1")!.resizableImage(withCapInsets:
UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0), resizingMode: .stretch)).cgColor
终于找到解决办法了!
编辑:适用于 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
}
您只需要:
创建 UINavigationBarAppearance 实例:
let largeTitleAppearance = UINavigationBarAppearance()
Apple 文档:
UINavigationBarAppearance - An object for customizing the appearance of a navigation bar.
配置一下:
largeTitleAppearance.configureWithOpaqueBackground()
"Opaque"这里是因为我们要设置彩色图像(但实际上无所谓,你设置什么配置)
设置背景图片:
largeTitleAppearance.backgroundImage = UIImage(named: "BackgroundImage.png") // Set here image that you need
将我们的 largeTitleAppearance 对象分配给 standardAppearance 和 scrollEdgeAppearance 导航栏字段:
self.navigationBar.standardAppearance = largeTitleAppearance // For large-navigationBar condition when it is collapsed
self.navigationBar.scrollEdgeAppearance = largeTitleAppearance // For large-navigationBar condition when it is expanded
Apple 文档:
.standardAppearance - The appearance settings for a standard-height navigation bar.
.scrollEdgeAppearance - The appearance settings to use when the edge of any scrollable content reaches the matching edge of the navigation bar.
这对我有帮助:https://sarunw.com/posts/uinavigationbar-changes-in-ios13/#going-back-to-old-style
iOS11如何为大标题NavigationBar设置自定义背景图片?我正在使用自定义子类,我已将其分配给情节提要中的 navigationControllers。
这就是我创建自定义导航栏的方式:
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")
}
}
奇怪的是,setBackgroundImage(image, for: .default)
不适用于大标题。它以前与 iOS 10 一起工作,如果我旋转 iPhone(并激活小导航栏)背景又回来了?
编辑:
backgroundImage
仍然呈现但不知何故被隐藏了。只有当您开始滚动并且 "normal" 导航栏出现时,背景图像才可见。在这种情况下, barTintColor
也被完全忽略。
在 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
}
}
我遇到了同样的问题,已由
修复删除 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!)
获取具有渐变颜色的图像
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
}
在 Xamarin 中它会是这样的:
this.NavigationBar.BackgroundColor = UIColor.Clear;
var gradientLayer = new CAGradientLayer
{
Frame = new CGRect(0, 0, UIApplication.SharedApplication.StatusBarFrame.Width,
UIApplication.SharedApplication.StatusBarFrame.Height + this.NavigationBar.Frame.Height),
Colors = new CGColor[]
{Constants.Defaults.Navigation.RealBlueColor.ToCGColor(), Constants.Defaults.Navigation.RealBlueColor.ToCGColor()}
};
UIGraphics.BeginImageContext(gradientLayer.Bounds.Size);
gradientLayer.RenderInContext((UIGraphics.GetCurrentContext()));
UIImage image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
this.View.Layer.InsertSublayer(gradientLayer, 0);
this.NavigationBar.BarTintColor = UIColor.FromPatternImage(image);
this.View.Layer.Insert可选。当我 "curling" 在 NavigationBar
上上下移动图像时我需要它试试这个代码 (Swift 4.0):
在viewDidLoad()中
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.black]
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
self.navigationItem.largeTitleDisplayMode = .automatic
self.navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.black]
} else {
//iOS <11.0
}
self.title = "Title"
self.navigationController?.navigationBar.barTintColor = UIColor(patternImage: #imageLiteral(resourceName: "nav_bg"))
self.navigationController?.navigationBar.isTranslucent = false
借用 oldrinmendez 的回答 - 该解决方案非常适合水平渐变。
对于垂直渐变,我能够通过在 scrollViewDidScroll 中再次调用它来使用 oldrinmendez 的答案中的相同函数。这会在用户滚动时不断调整渐变图像的高度。
从 oldrinmendez 的函数开始:
func imageWithGradient(startColor:UIColor, endColor:UIColor, size:CGSize, horizontally:Bool) -> 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)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
}
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
创建一个更新函数以使用您想要的选项调用它:
func updateImageWithGradient() {
let navBarHeight = self.navigationController?.navigationBar.frame.size.height
let statusBarHeight = UIApplication.shared.statusBarFrame.height
let heightAdjustment: CGFloat = 2
let gradientHeight = navBarHeight! + statusBarHeight + heightAdjustment
let bgimage = imageWithGradient(startColor: UIColor.red, endColor: UIColor.orange, size: CGSize(width: UIScreen.main.bounds.size.width, height: gradientHeight), horizontally: false)
navigationController?.navigationBar.barTintColor = UIColor(patternImage: bgimage!)
}
最后给 scrollViewDidScroll & ViewDidApper 添加更新函数: 使用 ViewDidAppear 返回正确的导航栏高度
override func viewDidAppear(_ animated: Bool) {
updateImageWithGradient()
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
DispatchQueue.main.async {
updateImageWithGradient()
}
}
更改 barTint 对我不起作用,所以我更改了 navigationBar 中的图层
navigationBar.layer.backgroundColor = UIColor(patternImage:
UIImage(named: "BG-Roof1")!.resizableImage(withCapInsets:
UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0), resizingMode: .stretch)).cgColor
终于找到解决办法了!
编辑:适用于 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
}
您只需要:
创建 UINavigationBarAppearance 实例:
let largeTitleAppearance = UINavigationBarAppearance()
Apple 文档:
UINavigationBarAppearance - An object for customizing the appearance of a navigation bar.
配置一下:
largeTitleAppearance.configureWithOpaqueBackground()
"Opaque"这里是因为我们要设置彩色图像(但实际上无所谓,你设置什么配置)
设置背景图片:
largeTitleAppearance.backgroundImage = UIImage(named: "BackgroundImage.png") // Set here image that you need
将我们的 largeTitleAppearance 对象分配给 standardAppearance 和 scrollEdgeAppearance 导航栏字段:
self.navigationBar.standardAppearance = largeTitleAppearance // For large-navigationBar condition when it is collapsed self.navigationBar.scrollEdgeAppearance = largeTitleAppearance // For large-navigationBar condition when it is expanded
Apple 文档:
.standardAppearance - The appearance settings for a standard-height navigation bar.
.scrollEdgeAppearance - The appearance settings to use when the edge of any scrollable content reaches the matching edge of the navigation bar.
这对我有帮助:https://sarunw.com/posts/uinavigationbar-changes-in-ios13/#going-back-to-old-style