如何更改 SwiftUI 警报配色方案?

问题描述 投票:0回答:2

我实现了更改应用程序配色方案的功能。除了其中有

.alert()
TextField
的配色方案之外,一切都工作正常。

如果是日光且配色方案更改为

.dark
,则
.alert()
配色方案仍为
.light
,包括
TextField

这意味着当您在

TextField
中输入内容时,前景色为白色,因为深色模式下的文本颜色变为白色,您无法真正看到您正在输入的内容。

类似,如果系统的配色方案是

.dark
并且应用程序的配色方案是白色,则
.alert
处于
.dark
模式并且文本是黑色,因为应用程序中的文本是黑色的。

.background()
foregroundColor()
应用于
TextField
VStack
没有任何效果。

有没有办法控制

.alert()
的配色方案?或者我是否必须寻找
.alert()
替代方案?

这里是一些重现该行为的代码。谢谢!

import SwiftUI

struct ContentView: View {
    @State private var showAlert = false
    @State private var addSomething: String = ""
    @State private var isSystemMode = false
    @State private var isDarkMode = false

    var body: some View {
        VStack {
            VStack {
                Toggle("Automatic (iOS Settings)", isOn: $isSystemMode)
                if !isSystemMode {
                    Toggle("Dark Mode", isOn: $isDarkMode)
                }
            }
            Button{
                self.showAlert = true
            } label: {
                Text("Add something")
                    .frame(maxWidth: .infinity)
            }
            .alert("Add something", isPresented: $showAlert, actions: {
                TextField("Something", text: $addSomething)
                Button("Done") {
                    // Some action
                }
                Button("Cancel", role: .cancel, action: {})
            }, message: {
                Text("Type in something")
            })
        }
        .padding()
        .preferredColorScheme(isSystemMode ? .none : isDarkMode ? .dark : .light)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
ios swift swiftui
2个回答
5
投票

我认为真正实现这项工作的唯一方法是制作您自己的自定义警报。以下是自定义警报的示例,但您可能需要根据您的需要对其进行修改:

struct CustomAlertView<Content: View>: View {

    @Environment(\.colorScheme) var colorScheme

    let title: String
    let description: String

    var cancelAction: (() -> Void)?
    var cancelActionTitle: String?

    var primaryAction: (() -> Void)?
    var primaryActionTitle: String?

    var customContent: Content?

    init(title: String,
         description: String,
         cancelAction: (() -> Void)? = nil,
         cancelActionTitle: String? = nil,
         primaryAction: (() -> Void)? = nil,
         primaryActionTitle: String? = nil,
         customContent: Content? = EmptyView()) {
        self.title = title
        self.description = description
        self.cancelAction = cancelAction
        self.cancelActionTitle = cancelActionTitle
        self.primaryAction = primaryAction
        self.primaryActionTitle = primaryActionTitle
        self.customContent = customContent
    }

    var body: some View {
        HStack {
            VStack(spacing: 0) {
                Text(title)
                    .font(.system(size: 16, weight: .semibold, design: .default))
                    .padding(.top)
                    .padding(.bottom, 8)

                Text(description)
                    .font(.system(size: 12, weight: .light, design: .default))
                    .multilineTextAlignment(.center)
                    .padding([.bottom, .trailing, .leading])

                customContent

                Divider()

                HStack {
                    if let cancelAction, let cancelActionTitle {
                        Button { cancelAction() } label: {
                            Text(cancelActionTitle)
                                .frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
                        }
                    }

                    if cancelActionTitle != nil && primaryActionTitle != nil {
                        Divider()
                    }

                    if let primaryAction, let primaryActionTitle {
                        Button { primaryAction() } label: {
                            Text("**\(primaryActionTitle)**")
                                .frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
                        }
                    }
                }.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 50, alignment: .center)
            }
            .frame(minWidth: 0, maxWidth: 400, alignment: .center)
            .background(.ultraThickMaterial)
            .cornerRadius(10)
            .padding([.trailing, .leading], 50)
        }
        .zIndex(1)
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
        .background(
            colorScheme == .dark
            ? Color(red: 0, green: 0, blue: 0, opacity: 0.4)
            : Color(red: 1, green: 1, blue: 1, opacity: 0.4)
        )
    }
}

用途:

struct ContentView: View {
    @State private var showAlert = false

    var body: some View {
        ZStack {
            Button("Show alert") {
                withAnimation {
                    showAlert.toggle()
                }
            }
            if showAlert {
                CustomAlertView(
                    title: "Alert title",
                    description: "Description here",
                    cancelAction: {
                        // Cancel action here
                        withAnimation {
                            showAlert.toggle()
                        }
                    },
                    cancelActionTitle: "Cancel",
                    primaryAction: {
                      // Primary action here
                        withAnimation {
                            showAlert.toggle()
                        }
                    },
                    primaryActionTitle: "Action",
                    customContent:
                        Text("Custom content here")
                        .padding([.trailing, .leading, .bottom])
                )
            }
        }
    }
}

如果您想包含文本字段,只需执行以下操作:

customContent:
    TextField("Text here", text: $text)
    .textFieldStyle(.roundedBorder)
    .padding([.trailing, .leading, .bottom])

Preview of custom alert


0
投票

通过像这样设置外观来为我工作:

 UIView.appearance(for: UITraitCollection(userInterfaceStyle: .light), whenContainedInInstancesOf: [UIAlertController.self]).tintColor = .red
 UIView.appearance(for: UITraitCollection(userInterfaceStyle: .dark), whenContainedInInstancesOf: [UIAlertController.self]).tintColor = .blue
© www.soinside.com 2019 - 2024. All rights reserved.