首页 文章

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

提问于
浏览
15

如何在iOS 11中为大型 Headers 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")
    }
}

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

Edit: backgroundImage 仍然呈现但不知何故被隐藏 . 仅当您开始滚动并出现"normal"导航栏时,才会看到backgroundImage . 在这种情况下, barTintColor 也被完全忽略 .
screenshot

GIF

6 回答

  • 0

    我有同样的问题,修复它

    删除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
    }
    
  • 13

    在iOS 11中,如果使用大型 Headers ,则不再需要设置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
        }
    }
    
  • 4

    试试这段代码(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
    
  • 0

    在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是可选的 . 当我在NavigationBar上的图像上下来时,我需要它

  • 1

    捎带对oldrinmendez的回答 - 该解决方案适用于水平渐变 .

    对于VERTICAL渐变,我可以通过在scrollViewDidScroll中再次调用它来使用oldrinmendez的答案中的相同函数 . 当用户滚动时,这会不断调整渐变图像的高度 .

    Start with the function from 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
        }
    

    Create an update function to call it with the options you want:

    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!)
        }
    

    Finally add the update function to scrollViewDidScroll & ViewDidApper: 使用ViewDidAppear以返回正确的导航栏高度

    override func viewDidAppear(_ animated: Bool) {
            updateImageWithGradient()
        }
    
    override func scrollViewDidScroll(_ scrollView: UIScrollView) {
         DispatchQueue.main.async {
            updateImageWithGradient()
           }
        }
    
  • 2

    更改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
    

相关问题