dark/light 外观变化后 macOS SwiftUI 按钮前景色发生变化

macOS SwiftUI button foreground color changes after dark/light appearance change

所以我 运行 在 playground 中使用下面的代码,我看到 2 个浅色按钮,然后我切换到深色模式。作为 SwiftUI 框架的一部分,两个按钮都将前景色更新为灰白色。然后我点击一个按钮,其他按钮上的前景色变为灰色。请参阅下面的视频。 使用 Xcode 13.1


import SwiftUI
import PlaygroundSupport

struct ContentView: View {
    var body: some View {
        VStack {
            HStack {
                Text("Current")
                    .font(.subheadline)
                    .fontWeight(.semibold)
                    .foregroundColor(.gray)
                    .frame(maxWidth: .infinity, alignment: .leading)
                Label("43.672490, -79.388932", systemImage: "location")
                    .frame(width: 175, alignment: .trailing)
            }
            HStack {
                Button {} label: {
                    Text(" Set Location")
                        .frame(width: 95)
                }
                Spacer()
                Button {} label: {
                    Text(" Set Travel")
                        .frame(width: 95)
                }
            }
        }
    }
}

PlaygroundPage.current.setLiveView(ContentView())

Appearance change button issue video

有人遇到过这个错误并有解决方案,还是我必须创建自定义按钮并手动修改前景色?

前景颜色似乎确实无法在明暗模式之间正确调整。但是,我能够使用考虑到不同外观的颜色来修复它,方法是在按钮上将其添加为 .foregroundColor()

struct ContentView: View {
    let buttonTextColor = Color(.secondaryLabelColor)
    var body: some View {
        VStack {
            HStack {
                Text("Current")
                    .font(.subheadline)
                    .fontWeight(.semibold)
                    .foregroundColor(.gray)
                    .frame(maxWidth: .infinity, alignment: .leading)
                Label("43.672490, -79.388932", systemImage: "location")
                    .frame(width: 175, alignment: .trailing)
            }
            HStack {
                Button {} label: {
                    Text(" Set Location")
                        .frame(width: 95)
                }
                .foregroundColor(buttonTextColor)
                Spacer()
                Button {} label: {
                    Text(" Set Travel")
                        .frame(width: 95)
                }
                .foregroundColor(buttonTextColor)
            }
        }
    }
}

值得向 Apple 提交错误报告,恕我直言。

编辑:

要准确模拟按钮,您需要使用自定义 ButtonStyle。我没有完全匹配颜色,你可以自己做,但这里是它如何工作的要点:

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme
    var buttonTextColor = Color(.labelColor)
    
    var body: some View {
        VStack {
            HStack {
                Text("Current")
                    .font(.subheadline)
                    .fontWeight(.semibold)
                    .foregroundColor(.gray)
                    .frame(maxWidth: .infinity, alignment: .leading)
                Label("43.672490, -79.388932", systemImage: "location")
                    .frame(width: 175, alignment: .trailing)
            }
            HStack {
                Button {} label: {
                    Text(" Set Location")
                        .frame(width: 95)
                }
                .buttonStyle(CustomButtonStyle())
                
                Spacer()
                Button {} label: {
                    Text(" Set Travel")
                        .frame(width: 95)
                }
            }
        }
    }
}

struct CustomButtonStyle : ButtonStyle {
    @Environment(\.colorScheme) var colorScheme
    
    func makeBody(configuration: Configuration) -> some View {
        if colorScheme == .light {
        configuration.label
                    .foregroundColor(configuration.isPressed ? Color.white : Color.black)
                    .padding(3)
                    .background(RoundedRectangle(cornerRadius: 5)
                                    .fill(configuration.isPressed ? Color.blue : Color.white)
                                    .shadow(color: .gray, radius: 2, x: 0, y: 2)
                    )
        } else {
            configuration.label
                        .foregroundColor(Color.white)
                        .padding(3)
                        .background(RoundedRectangle(cornerRadius: 5)
                                        .fill(configuration.isPressed ? Color.blue : Color.gray)
                                        .shadow(color: .gray, radius: 2, x: 0, y: 2)
                        )
        }
    }
}