我目前一直在使用此 Environment
变量来调整应用程序中 Dark
和 Light
模式的内容。
@Environment(.colorScheme) var colorScheme
我遇到的问题是使用 var
有条件地设置按钮样式。这种方法效果很好。
if colorScheme == .dark {
Button("Create Account", action: {
}).buttonStyle(CinderDarkButtonStyle(geometry: geometry))
} else {
Button("Create Account", action: {
}).buttonStyle(CinderLightButtonStyle(geometry: geometry))
}
但是这样做会导致我在相对简单的用户界面上到处重复代码。每当我尝试以这种方式执行此操作时,我都会遇到错误,指出我的类型不匹配。
Button("Create Account", action: {
//DO SOME ACTION
}).buttonStyle(
colorScheme == .dark ?
CinderDarkButtonStyle(geometry: geometry) :
CinderLightButtonStyle(geometry: geometry)
)
答案 0 :(得分:0)
您会收到错误消息,因为 CinderDarkButtonStyle
和 CinderLightButtonStyle
实际上是不同的类型。而且,ButtonStyle
具有关联类型,因此您不能直接转换为 ButtonStyle
。
如果这是一个普通的 View
而不是 ButtonStyle
,您可以使用 AnyView
进行一些类型擦除,以便类型相同。
在这种情况下,似乎只是移动关于在自定义按钮样式中显示哪种按钮样式的逻辑会更清晰:
struct MyTestView : View {
var body: some View {
GeometryReader { geometry in
Button("Create Account", action: {
//DO SOME ACTION
})
.buttonStyle(CinderButtonStyle(geometry: geometry))
}
}
}
struct CinderButtonStyle : ButtonStyle {
var geometry : GeometryProxy
@Environment(\.colorScheme) private var colorScheme
@ViewBuilder func makeBody(configuration: Configuration) -> some View {
switch colorScheme {
case .dark:
darkBody(configuration: configuration)
case .light:
lightBody(configuration: configuration)
@unknown default:
lightBody(configuration: configuration)
}
}
@ViewBuilder func lightBody(configuration: Configuration) -> some View {
configuration.label //light modifications
}
@ViewBuilder func darkBody(configuration: Configuration) -> some View {
configuration.label //dark modifications
}
}
更新,使用视图修饰符:
struct CinderButtonStyle : ButtonStyle {
var geometry : GeometryProxy
@Environment(\.colorScheme) private var colorScheme
@ViewBuilder func makeBody(configuration: Configuration) -> some View {
switch colorScheme {
case .dark:
lightAndDarkModifications(configuration: configuration)
.modifier(DarkModifier())
default:
lightAndDarkModifications(configuration: configuration)
.modifier(LightModifier())
}
}
@ViewBuilder func lightAndDarkModifications(configuration: Configuration) -> some View {
configuration.label
}
}
struct DarkModifier : ViewModifier {
func body(content: Content) -> some View {
content
}
}
struct LightModifier : ViewModifier {
func body(content: Content) -> some View {
content
}
}
答案 1 :(得分:0)
除了 @Don 所说的额外的 )
之外,CinderDarkButtonStyle
和 CinderLightButtonStyle
是不同的结构体。它们不是同一类型。
您可以做的是创建一个返回不透明类型的自定义函数,如this answer 中所述。尝试这样的事情:
struct ContentView: View {
@State var colorScheme = ColorScheme.dark
var body: some View {
GeometryReader { geometry in
Button("Create Account", action: {
//DO SOME ACTION
})
.buttonStyle(for: colorScheme, geometry: geometry) /// use custom buttonStyle function
}
}
}
extension Button {
@ViewBuilder
func buttonStyle(for colorScheme: ColorScheme, geometry: GeometryProxy) -> some View {
switch colorScheme {
case .light:
buttonStyle(CinderDarkButtonStyle(geometry: geometry))
case .dark:
buttonStyle(CinderLightButtonStyle(geometry: geometry))
}
}
}
以上基于 buttonStyle(CinderDarkButtonStyle(geometry: geometry))
在 buttonStyle(CinderLightButtonStyle(geometry: geometry))
和 colorScheme
修饰符之间切换。