How to implement something that can be LinearGradient, AngularGradient or RadialGradient?

I need to make something that can be used anywhere LinearGradient, AngularGradient and RadialGradient can be used. Since these are ShapeStyle, View, so I think what I need is to implement something like this:

struct MySomeGradient: ShapeStyle, View {
    let gradient: (What' type here?)

    // I know all the key values, in fact, its an enum
    init(key: String) {
        // will create any of LinearGradient, AngularGradient or RadialGradiant base on value of key
        if key == "AAAA" {
            self.gradient = LinearGradient(...)
        } else if key == "BBBB" {
            self.gradient = AngularGradient(...)
        } else if key == "CCCC" {
            self.gradient = RadialGradient(....)
        } else if etc ete  {
            self.gradient = some gradient ...
        }
    }
    
    // so how to implement this?
}

So I tried this:

struct MySomeGradient<Content: ShapeStyle & View>: ShapeStyle, View {
    static func _makeView<S>(view: _GraphValue<_ShapeView<S, ThemeColor<Content>>>, inputs: _ViewInputs) -> _ViewOutputs where S : Shape {
        <#code#>       // 😳
    }
    
    let gradient: Content

    enum Key: String, CaseIterable {
        case grain = "稻谷"
        case rainbow = "rainbow"
        case daynight = "daynight"
    }
    
    // I know all the key values, in fact, its an enum
    init(key: String) {
        // will create any of LinearGradient, AngularGradient or RadialGradiant base on value of key
        if key == "AAAA" {
            self.gradient = LinearGradient(...)
        } else if key == "BBBB" {
            self.gradient = AngularGradient(...)
        } else if key == "CCCC" {
            self.gradient = RadialGradient(....)
        } else if etc ete  {
            self.gradient = some gradient ...
        }
    }

    
    var body: some View {
        gradient
    }
}

So I let Xcode fill in the protocol stub and got this _makeView<S>(....). Do all these _ means this is not for public use?

1 Like

Newly introduced in Xcode Version 13.0 beta 3 (13A5192i) (SwiftUI 3 beta 3?): AnyShapeStyle makes this possible:

struct GradientView: View {
    let gradient: AnyShapeStyle

    enum Key: String, CaseIterable {
        case grain = "稻谷"
        case rainbow = "rainbow"
        case daynight = "daynight"
    }

    // I know all the key values, in fact, its an enum
    init(_ key: Key) {
        // will create any of LinearGradient, AngularGradient or RadialGradiant base on value of key
        switch key {
        case .grain:
            gradient = AnyShapeStyle(   // can now type erase!!!
                .linearGradient(colors: [.red, .blue, .teal], startPoint: .topLeading, endPoint: .bottomTrailing)
            )
        case .rainbow:
            gradient = AnyShapeStyle(
                Color.yellow
            )
        case .daynight:
            gradient = AnyShapeStyle(
                .conicGradient(Gradient(colors: [.yellow, .cyan, .purple]), center: .center)
            )
        }
    }


    var body: some View {
        Rectangle()
            // can be filled with whatever
            .fill(gradient)
    }

}
Terms of Service

Privacy Policy

Cookie Policy