【问题标题】:Custom Navigation Bar not rectangular自定义导航栏不是矩形
【发布时间】:2018-01-03 14:07:54
【问题描述】:

是否可以将导航栏自定义为如下图所示?显然,它的背景是透明的,而不是灰色的。

我试过了:

UINavigationBar.appearance().setBackgroundImage(UIImage(named:"pattern.png"),
                                                            for: .default)

这似乎捕获了导航栏的颜色,但没有捕获导航栏的格式。

我试图避免使用 UIView 或类似的东西创建自定义导航栏,因为这意味着对于这么小的更改需要大量额外的工作。我的应用有很多使用导航控制器的视图。

提前致谢。

【问题讨论】:

    标签: ios swift xcode uinavigationcontroller storyboard


    【解决方案1】:

    使用它来将 zigzag 模式添加到您的导航栏 (version2),或者您可以使用所需的模式创建自定义 UIImage (version1 (favorite))

    版本 1 使用 UIImage 并使用 self.navigationController?.navigationBar.setBackgroundImage 方法

    获取图片

    import UIKit
    
    extension UIImage {
        
        static func pathZigZagForCGRect(rect: CGRect) ->UIBezierPath
        {
            let width = rect.size.width
            let height = rect.size.height
            
            let zigZagWidth = CGFloat(7)
            let zigZagHeight = CGFloat(5)
            var yInitial = height-zigZagHeight
            
            var zigZagPath = UIBezierPath()
            zigZagPath.move(to: CGPoint(x:0, y:0))
            zigZagPath.addLine(to: CGPoint(x:0, y:yInitial))
            
            var slope = -1
            var x = CGFloat(0)
            var i = 0
            while x < width {
                x = zigZagWidth * CGFloat(i)
                let p = zigZagHeight * CGFloat(slope) - 5
                let y = yInitial + p
                let point = CGPoint(x: x, y: y)
                zigZagPath.addLine(to: point)
                slope = slope*(-1)
                i += 1
            }
            
            zigZagPath.addLine(to: CGPoint(x:width,y: 0))
            zigZagPath.addLine(to: CGPoint(x:0,y: 0))
            zigZagPath.close()
            return zigZagPath
        }
        
    
        static func zigZagImage(rect: CGRect,color:UIColor)->UIImage {
            
            UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
            var ctx = UIGraphicsGetCurrentContext()!
            ctx.clear(CGRect(x: 0, y: 0, width: rect.size.width, height: rect.size.height))
            
            ctx.setFillColor(color.cgColor)
            let path = UIImage.pathZigZagForCGRect(rect: rect)
            ctx.addPath(path.cgPath)
            ctx.fillPath()
            //draw triangle
            
            let img = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
            
            return img
        }
        
    }
    

    使用它

    override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            self.navigationController?.navigationBar.setBackgroundImage( UIImage.zigZagImage(rect: CGRect(x: 0, y: 0, width: (self.navigationController?.navigationBar.frame.size.width)!, height: (self.navigationController?.navigationBar.frame.height)! + 20),color:UIColor.red).resizableImage(withCapInsets: UIEdgeInsets.zero, resizingMode: .stretch), for: .default)
        }
    

    结果

    使用 layerMask 的版本 2

    func pathZigZagForView(givenView: UIView) ->UIBezierPath
        {
            let width = givenView.frame.size.width
            let height = givenView.frame.size.height
            
            let zigZagWidth = CGFloat(7)
            let zigZagHeight = CGFloat(5)
            var yInitial = height-zigZagHeight
            
            var zigZagPath = UIBezierPath()
            zigZagPath.move(to: CGPoint(x:0, y:0))
            zigZagPath.addLine(to: CGPoint(x:0, y:yInitial))
            
            var slope = -1
            var x = CGFloat(0)
            var i = 0
            while x < width {
                x = zigZagWidth * CGFloat(i)
                let p = zigZagHeight * CGFloat(slope) - 5
                let y = yInitial + p
                let point = CGPoint(x: x, y: y)
                zigZagPath.addLine(to: point)
                slope = slope*(-1)
                i += 1
            }
            
            zigZagPath.addLine(to: CGPoint(x:width,y: 0))
            zigZagPath.addLine(to: CGPoint(x:0,y: 0))
            zigZagPath.close()
            return zigZagPath
       }
    
    func applyZigZagEffect(givenView: UIView) {
        let shapeLayer = CAShapeLayer(layer: givenView.layer)
        shapeLayer.path = self.pathZigZagForView(givenView: givenView).cgPath
        shapeLayer.frame = givenView.bounds
        shapeLayer.masksToBounds = true
        givenView.layer.mask = shapeLayer
    }
    

    使用它

    override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            self.navigationController?.navigationBar.backgroundColor = UIColor.red
            self.applyZigZagEffect(givenView: (self.navigationController?.navigationBar)!)
        }
    

    希望对你有帮助

    【讨论】:

      【解决方案2】:

      我试图避免使用 UIView 或创建自定义导航栏 任何类似的事情,因为这将意味着很多额外的工作 这么小的变化。我的应用使用导航有很多视图 控制器。

      子类UINavigationController 并在其中包含的UINavigationBar 上实现自定义视图。

      然后,在应用中有导航控制器的任何地方,将其类替换为自定义子类。

      例如:

      class MyCustomNavigationController: UINavigationController {
      
          override func viewDidLoad() {
              // ... code to implement custom view
              // you may not necessarily want to put it in viewDidLoad...
          }
      
      }
      

      这样您只需编写一次自定义视图代码。自定义视图作为您的导航栏很可能是实现您想要的唯一方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-12
        • 1970-01-01
        • 2014-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多