'SwiftUI - create a single dashed line with SwiftUI

I need to create a single dashed line. I tried going about it by creating a Rectangle view with a dashed stroke. However, when setting the height of the rectangle to 1, it results in a double line as its showing both the top and bottom borders of the view.

This is the code:

Rectangle()
    .fill(Color.clear)
    .frame(height: 1, alignment: .bottom)
    .overlay(
        RoundedRectangle(cornerRadius: 0)
            .stroke(style: StrokeStyle(lineWidth: 1, dash: [5]))
            .foregroundColor(Color(UIColor.blue))
    )


Solution 1:[1]

Change the dash value to increase or decrease the number of dash in the line.

struct ContentView: View {
     var body: some View {
         Line()
           .stroke(style: StrokeStyle(lineWidth: 1, dash: [5]))
           .frame(height: 1)
    }
}

struct Line: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x: rect.width, y: 0))
        return path
    }
}

Result:

enter image description here

Solution 2:[2]

Depending on what you want to do, you can do something like this:

VStack {
    Path{ path in
        path.move(to: CGPoint(x: 20, y: 300))
        path.addLine(to: CGPoint(x: 200, y: 300))
    }
    .stroke(style: StrokeStyle( lineWidth: 10, dash: [5]))
    .foregroundColor(Color(UIColor.blue))
}

You will get something like this: enter image description here

Solution 3:[3]

Improved @kazi.munshimun solution. Vetical line and horizontal line:

struct VLine: Shape {
    func path(in rect: CGRect) -> Path {
        Path { path in
            path.move(to: CGPoint(x: rect.midX, y: rect.minY))
            path.addLine(to: CGPoint(x: rect.midX, y: rect.maxY))
        }
    }
}

struct HLine: Shape {
    func path(in rect: CGRect) -> Path {
        Path { path in
            path.move(to: CGPoint(x: rect.minX, y: rect.midY))
            path.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
        }
    }
}

Usage:

VLine().stroke(style: StrokeStyle(lineWidth: 1, dash: [5]))
HLine().stroke(style: StrokeStyle(lineWidth: 1, dash: [5]))

Solution 4:[4]

Here is an ultimate way for you to add and draw lines with more easier options:

struct CustomLineShapeWithAlignment: Shape {
    
    let stratPoint: Alignment
    let endPoint: Alignment
    
    init(stratPoint: Alignment, endPoint: Alignment) {
        self.stratPoint = stratPoint
        self.endPoint = endPoint
    }
    
    private func cgPointTranslator(alignment: Alignment, rect: CGRect) -> CGPoint {
        
        switch alignment {
        case .topLeading: return CGPoint(x: rect.minX, y: rect.minY)
        case .top: return CGPoint(x: rect.midX, y: rect.minY)
        case .topTrailing: return CGPoint(x: rect.maxX, y: rect.minY)
            
        case .leading: return CGPoint(x: rect.minX, y: rect.midY)
        case .center: return CGPoint(x: rect.midX, y: rect.midY)
        case .trailing: return CGPoint(x: rect.maxX, y: rect.midY)
            
        case .bottomLeading: return CGPoint(x: rect.minX, y: rect.maxY)
        case .bottom: return CGPoint(x: rect.midX, y: rect.maxY)
        case .bottomTrailing: return CGPoint(x: rect.maxX, y: rect.maxY)
        default: return CGPoint(x: rect.minX, y: rect.minY)
        }
        
    }

    func path(in rect: CGRect) -> Path {
        
        Path { path in
            
            path.move(to: cgPointTranslator(alignment: stratPoint, rect: rect))
            path.addLine(to: cgPointTranslator(alignment: endPoint, rect: rect))
            
        }
        
    }
    
}

use case:

struct ContentView: View {
    var body: some View {
        
        CustomLineShapeWithAlignment(stratPoint: .top, endPoint: .bottom)
            .stroke(style: StrokeStyle(lineWidth: 1.0, dash: [5]))
            .background(Color.red)
        
        ZStack {
            
            CustomLineShapeWithAlignment(stratPoint: .top, endPoint: .bottom)
                .stroke(style: StrokeStyle(lineWidth: 1.0, dash: [5]))
                .frame(width: 1.0)
            
            CustomLineShapeWithAlignment(stratPoint: .leading, endPoint: .trailing)
                .stroke(style: StrokeStyle(lineWidth: 1.0, dash: [5]))
                .frame(height: 1.0)
            
        }
        .background(Color.gray)
        
        CustomLineShapeWithAlignment(stratPoint: .topLeading, endPoint: .bottomTrailing)
            .stroke(style: StrokeStyle(lineWidth: 1.0, dash: [5]))
            .background(Color.blue)
        
    }
}

result:

enter image description here

Solution 5:[5]

import SwiftUI

public struct DashedDivider: View {
    private let overlayColor: Color
    
    public init(_ overlayColor: Color = Color(UIColor.systemGray)) {
        self.overlayColor = overlayColor
    }
    
    public var body: some View {
        HLine()
            .stroke(style: StrokeStyle(lineWidth: 1, dash: [5]))
            .foregroundColor(overlayColor)
            .frame(height: 1)
    }
}

struct HLine: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: CGPoint(x: rect.minX, y: rect.minY))
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
        return path
    }
}

struct DashedDivider_Previews: PreviewProvider {
    static var previews: some View {
        DashedDivider()
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Olcay ErtaÅŸ
Solution 3 Nikaaner
Solution 4 swiftPunk
Solution 5 Catalin