我有一个自定义视图:

public struct CustomView: View {
    var text1: String
    var text2: String

    public var body: some View {
        VStack {
            Text(text1).tag(0)
            Text(text2).tag(1)
        }
    }
}

我想创建视图修改器并将自定义样式参数传递给它:

struct Watermark: ViewModifier {
    var style: Style

    func body(content: Content) -> some View {
          if style == .one {
              // access Text with tag 0 and set foreground color to red
              // access Text with tag 1 and set foreground color to blue
          } else if style == .two {
              // access Text with tag 0 and set foreground color to black
              // access Text with tag 1 and set foreground color to pink
          }
}

如何从修改器访问内容子视图以更改其样式?

我想做一些类似于苹果对SF Image所做的事情

enter image description here

附言:我想使用精确的视图修饰符.我不想将样式作为参数传递给视图.因为我想构建复杂的自定义视图,其中可以包含7个以上的参数.我不想传递7个参数来查看初始值设定项.视图修改器看起来更漂亮.

推荐答案

您不应该使用tag来标识视图.tag是很难读懂的.它的视图特征键是一个内部类型,因此您需要使用Mirror.

您可以使用环境来代替.为您将拥有的7+参数中的每一个创建一个环境密钥.

在本例中,有2种 colored颜色 ,因此我将创建2个关键点.如果有更多的 colored颜色 ,我会使用一个数组作为值的键.

struct Color1Key: EnvironmentKey {
    static var defaultValue = AnyShapeStyle(.primary)
}

struct Color2Key: EnvironmentKey {
    static var defaultValue = AnyShapeStyle(.secondary)
}

extension EnvironmentValues {
    var color1: AnyShapeStyle {
        get { self[Color1Key.self] }
        set { self[Color1Key.self] = newValue }
    }
    var color2: AnyShapeStyle {
        get { self[Color2Key.self] }
        set { self[Color2Key.self] = newValue }
    }
}

编写您自己的从环境读取的视图修饰符,而不是tag个.

struct Color1Modifier: ViewModifier {
    @Environment(\.color1) var color1
    
    func body(content: Content) -> some View {
        content.foregroundStyle(color1)
    }
}

struct Color2Modifier: ViewModifier {
    @Environment(\.color2) var color2
    
    func body(content: Content) -> some View {
        content.foregroundStyle(color2)
    }
}

extension View {
    func color1() -> some View {
        modifier(Color1Modifier())
    }
    func color2() -> some View {
        modifier(Color2Modifier())
    }
}

// usage:
VStack {
    Text(text1).color1()
    Text(text2).color2()
}
.modifier(Watermark(style: ...))

然后,Watermark可以向环境写入:

func body(content: Content) -> some View {
    content
        .environment(\.color1, AnyShapeStyle(style == .one ? .red : .black))
        .environment(\.color2, AnyShapeStyle(style == .one ? .blue : .pink))
}

以下是相同概念的实现,但使用一个环境键保存一组 colored颜色 :

struct CustomView: View {
    var text1: String
    var text2: String
    
    public var body: some View {
        VStack {
            Text(text1).color(0)
            Text(text2).color(1)
        }
        .modifier(Watermark(style: ...))
    }
}

struct ColorsModifier: ViewModifier {
    let index: Int
    
    @Environment(\.colors) var colors
    
    func body(content: Content) -> some View {
        content.foregroundStyle(
            colors.indices.contains(index) ? colors[index] : AnyShapeStyle(.opacity(1))
        )
    }
}

extension View {
    func color(_ n: Int) -> some View {
        modifier(ColorsModifier(index: n))
    }
}

struct ColorsKey: EnvironmentKey {
    static var defaultValue: [AnyShapeStyle] = []
}

extension EnvironmentValues {
    var colors: [AnyShapeStyle] {
        get { self[ColorsKey.self] }
        set { self[ColorsKey.self] = newValue }
    }
}

struct Watermark: ViewModifier {
    enum Style {
        case one, two
    }
    
    var style: Style
    
    func body(content: Content) -> some View {
        content
            .environment(
                \.colors,
                style == .one ?
                 [.init(.red), .init(.blue)] :
                 [.init(.black), .init(.pink)]
            )
    }
}

Ios相关问答推荐

SwiftUI中ForEach和@ State数组的可能并发问题

SWIFT图表轴订购问题

执行devicectl:ProcessException时出错:进程异常退出:错误:命令超时超过5.0秒

@Query与SwiftData数据列表绑定

SwiftUI 图像与下拉视图切换一起 skip

'DismissAction'类型的值没有成员'wrappedValue'在SwiftUI的Xcode中

如何为视图的 colored颜色 和宽度设置动画?

如何快速设置条形按钮的图像?

UICollectionView - 水平滚动,水平布局?

在iOS7半透明导航栏中获取正确的 colored颜色

使用 AVAudioPlayer 播放声音

如何比较两个 UIImage 对象

iOS - 确保在主线程上执行

如何在 OS X 或 iOS(不使用格式塔)中确定运行时的操作系统版本?

@IBDesignable 崩溃代理

核心数据 - 无法在路径加载优化模型

使用 Xcode 4 的 iPhone 临时构建

在 iOS 上存储身份验证令牌 - NSUserDefaults 与 keys 串?

我可以通过 UIAppearance 代理设置哪些属性?

如何删除 Swift 数组中的所有 nil 元素?