iOS 11中带有大标题导航栏的自定义背景图像
如何在iOS 11中为大标题导航栏设置自定义背景图像?我正在使用一个自定义子类,我已经在故事板中分配给NavigationController 以下是创建自定义导航栏的方式:iOS 11中带有大标题导航栏的自定义背景图像,ios,swift,uinavigationbar,ios11,Ios,Swift,Uinavigationbar,Ios11,如何在iOS 11中为大标题导航栏设置自定义背景图像?我正在使用一个自定义子类,我已经在故事板中分配给NavigationController 以下是创建自定义导航栏的方式: class CustomNavigationController: UINavigationController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup afte
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(图像,例如:.default)
对大标题不起作用。它以前在iOS 10上工作过,如果我旋转iPhone(并激活小导航栏),背景会回来吗
编辑:
backgroundImage
仍被渲染,但不知何故被隐藏。只有当您开始滚动并且出现“正常”导航栏时,背景图像才可见。在这种情况下,BartinColor
也被完全忽略。
在iOS 11中,如果您使用大标题,则不再需要设置背景图像(删除其声明)。相反,你需要使用颜色
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并将Barint颜色与图案图像一起使用
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是可选的。当我在导航栏上上上下“卷曲”图像时,我需要它。请尝试以下代码(Swift 4.0):
在viewDidLoad()中
self.navigationController?.navigationBar.titleTextAttributes=[NSAttributedStringKey.foregroundColor:UIColor.black]
如果可用(iOS 11.0,*){
self.navigationController?.navigationBar.prefersLargeTitles=true
self.navigationItem.LarGetTitleDisplayMode=.automatic
self.navigationController?.navigationBar.largeTitleTextAttributes=[NSAttributedStringKey.foregroundColor:UIColor.black]
}否则{
//iOS借鉴奥尔德林门德斯的答案——该解决方案适用于水平梯度
对于垂直渐变,我可以使用oldrinmendez回答中的相同函数,在scrollViewDidScroll中再次调用它。这会在用户滚动时不断调整渐变图像的高度
从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!)
}
创建一个更新函数,用您想要的选项调用它:
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:使用ViewDidDisplay,以便返回正确的导航栏高度
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()方法中:
您所需要的只是:
创建UINavigationBarAppearance实例:
let largeTitleAppearance = UINavigationBarAppearance()
苹果文档:
UINavigationBarAppearance-用于自定义导航栏外观的对象
配置它:
largeTitleAppearance.configureWithOpaqueBackground()
这里的“不透明”是因为我们想要设置彩色图像(但实际上这并不重要,您将设置什么配置)
设置背景图像:
largeTitleAppearance.backgroundImage = UIImage(named: "BackgroundImage.png") // Set here image that you need
将我们的LarGetTitleAppearance对象分配给standardAppearance和ScrolledAppearance导航栏的字段:
self.navigationBar.standardAppearance = largeTitleAppearance // For large-navigationBar condition when it is collapsed
self.navigationBar.scrollEdgeAppearance = largeTitleAppearance // For large-navigationBar condition when it is expanded
苹果文档:
.standardAppearance-标准高度导航栏的外观设置
.scrollEdgeAppearance-任何可滚动内容的边缘到达导航栏的匹配边缘时使用的外观设置
这对我很有帮助:hi@alexkaessner。你找到问题的解决方案了吗?@OceanBlue否!:/我刚刚检查了一下新的导航栏。对于显示的大布局,似乎有一个完全不同的视图,但该视图没有改变。可以设置导航栏背景色或BartinColor。但不幸的是,我不能t设置导航栏背景图像。这是ios 11的错误吗?你知道什么吗?@OceanBlue我刚刚添加了一些分析信息,但似乎是个错误。我稍后将向苹果提交报告!@Tulleb一点也不。苹果将其标记为“33345493的副本”,但问题仍然悬而未决。感谢您的帖子,但这不是一个真正的解决方案。我还进行了一些测试和分析,似乎我必须坚持使用传统的导航栏(目前)。感谢您的回答。您知道导航栏背景图像的大小吗(示例中的navigationBarBackground)?我也尝试过,但我希望图像被拉伸而不是平铺。我的图像有一个渐变…或者有没有办法更改模式图像:
?好的,我现在已经测试过了,问题仍然是平铺。如果我旋转iPhone,渐变太短并且重复。而且“水平:false”也不起作用正确。这只是一个橙色的条背景。救世主:-)如果我们想拥有自己的背景图像,没有图案或渐变色,那该怎么办?我只想展示一幅简单的图像。你知道导航栏背景图像的大小吗?这对常规标题大小和大标题大小都非常有效,谢谢。不,这里同样适用于iOS 12。这是更正iOS 13中的解决方案。UIColor(图案图像:)解决方案只是黑客。太棒了,这是正确的解决方案!感谢您将其分享到这篇旧帖子。疯狂的是,苹果花了很长时间才介绍了这一点。顺便说一句,如果您需要更改背景图像拉伸/定位,也可以看看SwiftUI的作品!@HarryJ Ohh,这是我需要的。您需要使用UIHostingController还是你是另一种方式吗?