SwiftUI: How to draw filled and stroked shape?

You can also use strokeBorder and background in combination.

Code:

Circle()
    .strokeBorder(Color.blue,lineWidth: 4)
    .background(Circle().foregroundColor(Color.red))

Result:


You can draw a circle with a stroke border

struct ContentView: View {
    var body: some View {
        Circle()
            .strokeBorder(Color.green,lineWidth: 3)
            .background(Circle().foregroundColor(Color.red))
   }
}

circle with stroked border


My workaround:

import SwiftUI

extension Shape {
    /// fills and strokes a shape
    public func fill<S:ShapeStyle>(
        _ fillContent: S, 
        stroke       : StrokeStyle
    ) -> some View {
        ZStack {
            self.fill(fillContent)
            self.stroke(style:stroke)
        }
    }
}

Example:


struct ContentView: View {
    // fill gradient
    let gradient = RadialGradient(
        gradient   : Gradient(colors: [.yellow, .red]), 
        center     : UnitPoint(x: 0.25, y: 0.25), 
        startRadius: 0.2, 
        endRadius  : 200
    )
    // stroke line width, dash
    let w: CGFloat   = 6       
    let d: [CGFloat] = [20,10]
    // view body
    var body: some View {
        HStack {
            Circle()
                // ⭐️ Shape.fill(_:stroke:)
                .fill(Color.red, stroke: StrokeStyle(lineWidth:w, dash:d))
            Circle()
                .fill(gradient, stroke: StrokeStyle(lineWidth:w, dash:d))
        }.padding().frame(height: 300)
    }
}

Result:

fill and stroke circles


Seems like it's either ZStack or .overlay at the moment.

The view hierarchy is almost identical - according to Xcode.

struct ContentView: View {

    var body: some View {

        VStack {
            Circle().fill(Color.red)
                .overlay(Circle().stroke(Color.blue))
            ZStack {
                 Circle().fill(Color.red)
                 Circle().stroke(Color.blue)
            }
        }

    }

}

Output:

enter image description here


View hierarchy:

enter image description here


For future reference, @Imran's solution works, but you also need to account for stroke width in your total frame by padding:

struct Foo: View {
    private let lineWidth: CGFloat = 12
    var body: some View {
        Circle()
            .stroke(Color.purple, lineWidth: self.lineWidth)
        .overlay(
            Circle()
                .fill(Color.yellow)
        )
        .padding(self.lineWidth)
    }
}

enter image description here