简体   繁体   中英

Change navigationBar bottom border to a dashed line in swift

I would like to change my navigationBar to have a dotted line as its border like so:

屏幕截图

I've found a wonderful answer in this thread about how to change the color of a navigationBar border: Change navigation bar bottom border color Swift In particular: https://stackoverflow.com/a/46224261/436014

Via a UIColor extension:

extension UIColor {

    /// Converts this `UIColor` instance to a 1x1 `UIImage` instance and returns it.
    ///
    /// - Returns: `self` as a 1x1 `UIImage`.
    func as1ptImage() -> UIImage {
        UIGraphicsBeginImageContext(CGSize(width: 1, height: 1))
        setFill()
        UIGraphicsGetCurrentContext()?.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
        let image = UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
        UIGraphicsEndImageContext()
        return image
    }
}

I was wondering if there was any way to adapt this to build out a dashed line instead. I was thinking it could somehow be done by drawing a fill in alternating colors, but am confused since it's all an extension off of a single UIcolor

navigationController.navigationBar.shadowImage = UIColor.black.as1ptImage()

Thus, something like the following clearly won't work:

UIGraphicsBeginImageContext(CGSize(width: 1, height: 4))
UIGraphicsGetCurrentContext()?.fill(CGRect(x: 0, y: 0, width: 1, height: 1))
UIGraphicsGetCurrentContext()?.fill(CGRect(x: 1, y: 0, width: 3, height: 1))

I was wondering if anyone has an idea how to go about this

Ok, I managed to find a solution through the help of the API documentation for CALayer: https://developer.apple.com/documentation/quartzcore/cashapelayer/1521921-linedashpattern

And this SO thread about converting a CALayer to UIImage: UIImage from CALayer in iOS

The overall process is:

  1. Create a CALayer
  2. Give this CALayer a frame
  3. Draw a dashed line
  4. Convert to UIImage
  5. Use this UIImage as the navigationBar.shadowImage

The nice thing is that it tiles appropriately, so the CALayer/UIImage just need to be as wide as the dashed line you are generating.

    extension UIImage {
        class func imageWithLayer(layer: CALayer) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(layer.bounds.size, layer.isOpaque, 0.0)
            layer.render(in: UIGraphicsGetCurrentContext()!)
            guard let img = UIGraphicsGetImageFromCurrentImageContext() else { return UIImage() }
            UIGraphicsEndImageContext()
            return img
        }
    }


    let layer = CALayer()
    layer.frame = CGRect(x: 0, y: 0, width: 6, height: 1)
    let shapeLayer = CAShapeLayer()
    shapeLayer.strokeColor = UIColor.black.cgColor
    shapeLayer.lineWidth = 1
    shapeLayer.lineDashPattern = [4,2]
    let path = CGMutablePath()
    path.addLines(between: [CGPoint(x:1, y: 0), CGPoint(x: 6, y:0)])
    shapeLayer.path = path
    layer.addSublayer(shapeLayer)
    navigationController.navigationBar.shadowImage = UIImage.imageWithLayer(layer: layer)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM