41

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

5 Answers 5

79

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

Sign up to request clarification or add additional context in comments.

4 Comments

Yup, cleaner solution as we use rect for dynamic sizes. However just one tiny thing... instead of DashedLine, it should be called simply Line :P
How to make this vertical ?
path.addLine(to: CGPoint(x: 0, y: rect.height)) instead on path.addLine(to: CGPoint(x: rect.width, y: 0)) in Line class.
@staticVoidMan it should be called HLine :P
17

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

3 Comments

With this solution, the coordinates of the line are fixed, so when the line is actually placed in the app UI, the line is in different places depending on screen size. How can we do this without hard coding coordinates? I need it to be placed between two other views (in an HStack) and centered.
@Tdg10e They are fixed for the given View. You can use that code and move around that line the same way as you would move anything else (Text(), Image()) using padding, offset, Spacer etc.
is it possible to tilt the dashes ?
16

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]))

Comments

7

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

Comments

2
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()
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.