42

I want to know how to make a dashed line in swift like this: - - - - - - - - instead of a regular straight line like this: ----------------, I know that i can make multiple lines but that will require so much unnecessary code if i can just write it in 1 line. Btw it has to be in CoreGraphics.

A. Steiness
  • 423
  • 1
  • 4
  • 7

7 Answers7

76

Swift 4

@IBOutlet var dashedView: UIView!

func drawDottedLine(start p0: CGPoint, end p1: CGPoint, view: UIView) {
    let shapeLayer = CAShapeLayer()
    shapeLayer.strokeColor = UIColor.lightGray.cgColor
    shapeLayer.lineWidth = 1
    shapeLayer.lineDashPattern = [7, 3] // 7 is the length of dash, 3 is length of the gap.

    let path = CGMutablePath()
    path.addLines(between: [p0, p1])
    shapeLayer.path = path
    view.layer.addSublayer(shapeLayer)
}

Call function

drawDottedLine(start: CGPoint(x: dashedView.bounds.minX, y: dashedView.bounds.minY), end: CGPoint(x: dashedView.bounds.maxX, y: dashedView.bounds.minY), view: dashedView)

With the above you will have a straight line, you can also change points as you wish, for example if you change the end point's y from dashedView.bounds.minY to dashedView.bounds.maxY you will have diagonal.

If you will use it in a subclass of UIView you won't have the outlet so you will use it with self instead.

mike vorisis
  • 2,786
  • 6
  • 40
  • 74
Fan Jin
  • 2,412
  • 17
  • 25
  • Here layer not difined – Vineesh TP Jul 17 '18 at 11:17
  • 2
    Hi @VineeshTP, the layer is from "view.layer" the view which you wish to add the dashed-line. – Fan Jin Jul 25 '18 at 21:54
  • If we have selected iphone 8 in storyboard and then, if we apply this code and run it on iPhone 5s, then dashed line goes beyond the width. – Karanveer Singh Mar 28 '19 at 09:08
  • The start and end point of the dashed line is attached to the view, so please make sure your view doesn't go over the bounds in iPhone 5s. – Fan Jin Apr 09 '19 at 22:11
  • You must also make the `dashedView` background .clear if you want the non-dotted line to disappear if you drew that with constraints in the storyboard – craft Nov 17 '20 at 22:08
40

You create Dashed Lines the same way as Objective-C, except that you'll use Swift.

Here is how you do it using UIBezierPath:

let  path = UIBezierPath()

let  p0 = CGPoint(x: self.bounds.minX, y: self.bounds.midY)
path.move(to: p0)

let  p1 = CGPoint(x: self.bounds.maxX, y: self.bounds.midY)
path.addLine(to: p1)

let  dashes: [ CGFloat ] = [ 16.0, 32.0 ]
path.setLineDash(dashes, count: dashes.count, phase: 0.0)

path.lineWidth = 8.0
path.lineCapStyle = .butt
UIColor.magenta.set()
path.stroke()

Here is how to draw Dotted Lines using UIBezierPath:

let  path = UIBezierPath()

let  p0 = CGPointMake(CGRectGetMinX(self.bounds), CGRectGetMidY(self.bounds))
path.moveToPoint(p0)

let  p1 = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMidY(self.bounds))
path.addLineToPoint(p1)

let  dashes: [ CGFloat ] = [ 0.0, 16.0 ]
path.setLineDash(dashes, count: dashes.count, phase: 0.0)
path.lineWidth = 8.0
path.lineCapStyle = .Round
UIColor.magentaColor().set()
path.stroke()

Here is how to draw Dashed Lines Using CGContext:

let  context: CGContext = UIGraphicsGetCurrentContext()!

let  p0 = CGPointMake(CGRectGetMinX(self.bounds), CGRectGetMidY(self.bounds))
CGContextMoveToPoint(context, p0.x, p0.y)

let  p1 = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMidY(self.bounds))
CGContextAddLineToPoint(context, p1.x, p1.y)

let  dashes: [ CGFloat ] = [ 16.0, 32.0 ]
CGContextSetLineDash(context, 0.0, dashes, dashes.count)

CGContextSetLineWidth(context, 8.0)
CGContextSetLineCap(context, .Butt)
UIColor.blueColor().set()
CGContextStrokePath(context)
Community
  • 1
  • 1
user3230875
  • 689
  • 6
  • 4
  • Line not coming when I am passing two buttons bound as parameter, How to draw dotted line between two UIbutton. here is my code let path = UIBezierPath() let p0 = CGPointMake(CGRectGetMinX(self.button1.bounds), CGRectGetMidY(self.button1.bounds)) path.moveToPoint(p0) let p1 = CGPointMake(CGRectGetMaxX(self.button2.bounds), CGRectGetMidY(self.button2.bounds)) path.addLineToPoint(p1) – Sagar Snehi Mar 30 '17 at 07:39
23

By Using Custom Class inherited from UIView also supports Storyboard.

All you need to do is make a view in storyboard assign class to that view and see the magic in storyboard.

@IBDesignable
class DashedLineView : UIView {
    @IBInspectable var perDashLength: CGFloat = 2.0
    @IBInspectable var spaceBetweenDash: CGFloat = 2.0
    @IBInspectable var dashColor: UIColor = UIColor.lightGray


    override func draw(_ rect: CGRect) {
        super.draw(rect)
        let  path = UIBezierPath()
        if height > width {
            let  p0 = CGPoint(x: self.bounds.midX, y: self.bounds.minY)
            path.move(to: p0)

            let  p1 = CGPoint(x: self.bounds.midX, y: self.bounds.maxY)
            path.addLine(to: p1)
            path.lineWidth = width

        } else {
            let  p0 = CGPoint(x: self.bounds.minX, y: self.bounds.midY)
            path.move(to: p0)

            let  p1 = CGPoint(x: self.bounds.maxX, y: self.bounds.midY)
            path.addLine(to: p1)
            path.lineWidth = height
        }

        let  dashes: [ CGFloat ] = [ perDashLength, spaceBetweenDash ]
        path.setLineDash(dashes, count: dashes.count, phase: 0.0)

        path.lineCapStyle = .butt
        dashColor.set()
        path.stroke()
    }

    private var width : CGFloat {
        return self.bounds.width
    }

    private var height : CGFloat {
        return self.bounds.height
    }
}
Amit Kumar
  • 583
  • 5
  • 16
15

Here's an easy to use UIView that draws a dashed line.

I took @Fan Jin's answer and made an UIView subclass that should work just fine with Auto Layout.

Swift 5.3, Xcode 12

import UIKit

public class DashedView: UIView {

    public struct Configuration {
        public var color: UIColor
        public var dashLength: CGFloat
        public var dashGap: CGFloat

        public init(
            color: UIColor,
            dashLength: CGFloat,
            dashGap: CGFloat) {
            self.color = color
            self.dashLength = dashLength
            self.dashGap = dashGap
        }

        static let `default`: Self = .init(
            color: .lightGray,
            dashLength: 7,
            dashGap: 3)
    }

    // MARK: - Properties

    /// Override to customize height
    public class var lineHeight: CGFloat { 1.0 }

    override public var intrinsicContentSize: CGSize {
        CGSize(width: UIView.noIntrinsicMetric, height: Self.lineHeight)
    }

    public final var config: Configuration = .default {
        didSet {
            drawDottedLine()
        }
    }

    private var dashedLayer: CAShapeLayer?

    // MARK: - Life Cycle

    override public func layoutSubviews() {
        super.layoutSubviews()

        // We only redraw the dashes if the width has changed.
        guard bounds.width != dashedLayer?.frame.width else { return }

        drawDottedLine()
    }

    // MARK: - Drawing

    private func drawDottedLine() {
        if dashedLayer != nil {
            dashedLayer?.removeFromSuperlayer()
        }

        dashedLayer = drawDottedLine(
            start: bounds.origin,
            end: CGPoint(x: bounds.width, y: bounds.origin.y),
            config: config)
    }

}

// Thanks to: https://stackoverflow.com/a/49305154/4802021
private extension DashedView {
    func drawDottedLine(
        start: CGPoint,
        end: CGPoint,
        config: Configuration) -> CAShapeLayer {
        let shapeLayer = CAShapeLayer()
        shapeLayer.strokeColor = config.color.cgColor
        shapeLayer.lineWidth = Self.lineHeight
        shapeLayer.lineDashPattern = [config.dashLength as NSNumber, config.dashGap as NSNumber]

        let path = CGMutablePath()
        path.addLines(between: [start, end])
        shapeLayer.path = path
        layer.addSublayer(shapeLayer)

        return shapeLayer
    }
}

Clément Cardonnel
  • 4,232
  • 3
  • 29
  • 36
  • Thank you so much. This answer is perfect for me. Will you please modify this class so that we can use this to create both vertical and horizontal line. Like, we will pass orientation param on configuration and based on that line will be drawn. and orientation param will be enum. something like this `enum Orientation { case HORIZONTAL case VERTICAL }` Thanks again. – Md. Arif May 11 '21 at 04:07
  • Only using this way I was able to add a dashed line to my layout. Thank you – josher932 Oct 31 '22 at 23:25
9

My extension method built from @FanJins answer

extension UIView {

    func createDashedLine(from point1: CGPoint, to point2: CGPoint, color: UIColor, strokeLength: NSNumber, gapLength: NSNumber, width: CGFloat) {
        let shapeLayer = CAShapeLayer()

        shapeLayer.strokeColor = color.cgColor
        shapeLayer.lineWidth = width
        shapeLayer.lineDashPattern = [strokeLength, gapLength]

        let path = CGMutablePath()
        path.addLines(between: [point1, point2])
        shapeLayer.path = path
        layer.addSublayer(shapeLayer)
    }
}

Then calling method looks something like this:

let topPoint = CGPoint(x: view.frame.midX, y: view.bounds.minY)
let bottomPoint = CGPoint(x: view.frame.midX, y: view.bounds.maxY)

view.createDashedLine(from: topPoint, to: bottomPoint, color: .black, strokeLength: 4, gapLength: 6, width: 2)
nullforlife
  • 1,354
  • 2
  • 18
  • 30
8

Pretty easy UIView Extension for SWIFT 4.2:

extension UIView {
    private static let lineDashPattern: [NSNumber] = [2, 2]
    private static let lineDashWidth: CGFloat = 1.0

    func makeDashedBorderLine() {
        let path = CGMutablePath()
        let shapeLayer = CAShapeLayer()
        shapeLayer.lineWidth = UIView.lineDashWidth
        shapeLayer.strokeColor = UIColor.lightGray.cgColor
        shapeLayer.lineDashPattern = UIView.lineDashPattern
        path.addLines(between: [CGPoint(x: bounds.minX, y: bounds.height/2),
                                CGPoint(x: bounds.maxX, y: bounds.height/2)])
        shapeLayer.path = path
        layer.addSublayer(shapeLayer)
    }
}
Joshua Hart
  • 772
  • 1
  • 21
  • 31
1

Objective C

@user3230875 answer helped me to understand what's needed to draw a dotted line.
so I hope this answer might help an Obj-C seeker

//dashed line
    path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(dashedLineStartX, dashedLineStartY)];
    [path addLineToPoint:CGPointMake(dashedLineEndX, dashedLineEndY)];
    path.lineWidth = 5;
    [color setStroke];
    CGFloat dashes[] = {4.0,8.0};
    [path setLineDash:dashes count:2 phase:0.0];
    path.lineCapStyle = kCGLineCapButt;
    [path stroke];
Sam
  • 406
  • 1
  • 11
  • 24