【问题标题】:SwiftUI: ViewModifier where content is a ShapeSwiftUI:内容是形状的 ViewModifier
【发布时间】:2020-10-22 04:37:10
【问题描述】:

以下代码可以正常工作。所以真的,我很好......但我想了解 ViewModifiers......所以我的目标是将不变的东西与动态的东西分开来创建一个 .cardify() 自定义修改器来调用形状视图。

struct SetCard: View {
    
    let pips: Int
    let shape: SetCardShape
    let color: Color
    let shading: Double
    let isSelected: Bool
    
    var body: some View {
        
        ZStack {
            VStack {
                ForEach( 0..<pips ) { _ in
                    ZStack {
                        getShape(self.shape).opacity(self.shading).foregroundColor(self.color)
                        getShape(self.shape).stroke().foregroundColor(self.color)
                    }
                }
            }
            .padding() // for shape in RoundedRect
            RoundedRectangle(cornerRadius: 10).stroke(lineWidth: isSelected ? 3.0 : 1.0).foregroundColor(.orange)
        }
        .scaleEffect(isSelected ? 0.60 : 1.0 )
        .padding() // for spacing between cards 
    }
}

再次,出于学术/学习的原因,我想简化这个结构,并使用自定义修饰符将主要内容转换为标准卡片。

下面的代码块仅在我注释掉Cardify ViewModifier 结构中的第二行content 时才有效。所有使用填充形状作为点的卡片都可以很好地渲染。需要描边(即未填充)形状的卡片需要我的 Cardify ViewModifer 中的第二个 content 才能工作。

第二个内容行产生错误:

Cardify.Content 类型的值(又名_ViewModifier_Content)没有成员foregroundColor

注释掉 .foregroundColor() 会产生错误: Cardify.Content(又名_ViewModifier_Content)类型的值没有成员笔划

struct SetCardWithCardify: View {
    
    let pips: Int
    let shape: SetCardShape
    let color: Color
    let shading: Double
    let isSelected: Bool
    
    var body: some View {
        ZStack {
            getShape(shape)
            .modifier(Cardify(pips: pips, shape: shape, color: color, shading: shading, isSelected: isSelected))
        }
    .scaleEffect(isSelected ? 0.60 : 1.0 )
        .padding() // for spacing between cards 
    }
}


struct Cardify: ViewModifier {
    
    var pips: Int
    var shape: SetCardShape
    var color: Color
    var shading: Double
    var isSelected: Bool
    
    func body(content: Content)  -> some View {
    
        ZStack {
            VStack {
                ForEach( 0..<pips ) { _ in
                    ZStack {
                        content.opacity(self.shading).foregroundColor(self.color)
                        content.stroke().foregroundColor(self.color)
                    }
                }
            }
            .padding() // for shape in RoundedRect
            RoundedRectangle(cornerRadius: 10).stroke(lineWidth: isSelected ? 3.0 : 1.0).foregroundColor(.orange)
        }
    }
}

以防万一这很重要,以下代码是getShape() 的来源,这是Cardify ViewModifier 中content 的来源。

func getShape(_ shape: SetCardShape ) -> some Shape {
    switch shape {
    case .circle:
        return AnyShape( Circle() )
    case .diamond:
        return AnyShape( SetDiamond() )
    case .squiggle:
        return AnyShape( SetSquiggle() )
    }
}


struct AnyShape: Shape {
    
    func path(in rect: CGRect) -> Path {
        return _path(rect)
    }
    
    init<S: Shape>(_ wrapped: S) {
        _path = { rect in
            let path = wrapped.path(in: rect)
            return path
        }
    }
    private let _path: (CGRect) -> Path
}

Diamond() 和 Squiggle() 是符合 Shape 协议的结构,从 `func path(in rect: CGRect) -> 这些结构中的路径正确返回路径。

我已尝试将第二个内容行向下转换为:

(content as! Shape).blah blah blah 这会产生错误:

Protocol Shape 只能用作通用约束,因为它具有 Self 或关联的类型要求。

我也试过了:

(content as! Path)

这不会产生任何编译时错误,但在执行时会失败并出现错误:

运行时遇到问题,请检查您的代码是否存在此行附近的错误。 (表示第二个内容行)。

我该怎么做才能让编译器知道这是什么类型的内容,这样 stroke() 和 foregroundColor() 才能工作?

【问题讨论】:

    标签: swift struct stroke viewmodifier


    【解决方案1】:

    我不确定你是否可以,但你可以使用 Shape 上的扩展来近似它:

    extension Shape {
        func modified() -> some View {
            self
                .foregroundColor(Color.secondary.opacity(0.5))
        }
    }
    
    // Usage example
    struct ContentView: View {
        var body: some View {
            VStack {
                Rectangle().modified()
                Capsule().modified()
            }
        }
    }
    

    但是,与视图修改器不同的是,您无法访问环境,因此它有些受限。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-11
      • 1970-01-01
      • 2018-01-02
      • 2019-12-16
      • 1970-01-01
      相关资源
      最近更新 更多