SwiftUI - Как проверить, включен ли темный режим?

Как проверить, включен ли темный режим на устройстве. Я хочу проверить это изнутри вида и условно показать или скрыть тень.

Я думал, что смогу просто получить цветовую схему из окружающей среды, но я думаю, что мне что-то не хватает.

struct FloatingAddButton : View {

    @Environment(\.colorScheme) var colorScheme 

    @Binding var openAddModal: Bool

    var body : some View {
        VStack {
            Spacer()
            HStack() {
                Spacer()
                Button(action: {

                    self.openAddModal = true

                }) {

                    ZStack {
                        Circle()
                            .foregroundColor(Color(RetroTheme.shared.appMainTint))
                            .frame(width: 50, height: 50, alignment: .center)
                        if(self.colorScheme == .light) {
                            .shadow(color: .secondary, radius: 5, x: 0, y: 0)
                        }

                        Image(systemName: "plus")
                            .foregroundColor(Color.white)
                    }

                } // End Button
            }
        }
    }

}

5 ответов

В моем коде есть простое расширение View, которое делает код более читаемым. С его помощью я могу условно применять модификаторы:

.conditionalModifier(self.colorScheme == .light, LightShadow())

Полная реализация приведена ниже:

extension View {
    // If condition is met, apply modifier, otherwise, leave the view untouched
    public func conditionalModifier<T>(_ condition: Bool, _ modifier: T) -> some View where T: ViewModifier {
        Group {
            if condition {
                self.modifier(modifier)
            } else {
                self
            }
        }
    }
}
struct FloatingAddButton : View {

    @Environment(\.colorScheme) var colorScheme

    @Binding var openAddModal: Bool

    var body : some View {
        VStack {
            Spacer()
            HStack() {
                Spacer()
                Button(action: { self.openAddModal = true }) {

                    ZStack {
                        Circle()
                            .foregroundColor(Color(.red))
                            .frame(width: 50, height: 50, alignment: .center)
                            .conditionalModifier(self.colorScheme == .light, LightShadow())

                        Image(systemName: "plus")
                            .foregroundColor(Color.white)
                    }
                }

            } // End Button

        }
    }
}

struct LightShadow: ViewModifier {
    func body(content: Content) -> some View {
        content.shadow(color: .secondary, radius: 5, x: 0, y: 0)
    }
}

Если у вас когда-нибудь был случай, когда вы захотели применить разные модификаторы для true и false, вот еще одно расширение:

extension View {
    // Apply trueModifier if condition is met, or falseModifier if not.
    public func conditionalModifier<M1, M2>(_ condition: Bool, _ trueModifier: M1, _ falseModifier: M2) -> some View where M1: ViewModifier, M2: ViewModifier {
        Group {
            if condition {
                self.modifier(trueModifier)
            } else {
                self.modifier(falseModifier)
            }
        }
    }
}

SwiftUI

С \.colorScheme ключ Environment переменная:

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        Text(colorScheme == .dark ? "In dark mode" : "In light mode")
    }
}

Кроме того, он автоматически обновляется при изменении цветовой схемы среды.


UIKit

Для проверки тока все объекты соответствуют UITraitEnvironment протокол, включая все UIView подклассы и все UIViewConttroller подклассы имеют доступ к текущему стилю:

myUIView.traitCollection.userInterfaceStyle == .dark
myUIViewController.traitCollection.userInterfaceStyle == .dark

Чтобы обнаружить изменение стиля, вот полный подробный ответ

Спасибо @dfd за указание на то, что я не могу использовать оператор if с модификатором. Я обновил свой код вот так. Это просто возвращает разные версии круга в светлом и темном режиме.

if colorScheme == .light {
    Circle()
        .foregroundColor(Color(RetroTheme.shared.appMainTint))
        .frame(width: 50, height: 50, alignment: .center)
        .shadow(color: .secondary, radius: 5, x: 0, y: 0)
} else {
    Circle()
        .foregroundColor(Color(RetroTheme.shared.appMainTint))
        .frame(width: 50, height: 50, alignment: .center)
}

Вы которые с помощьюcolorSchemeправильно. Но похоже, что у вас другая проблема - размещение модификатора внутриifзаявление. Я обнаружил, что в отличие отView, модификаторы не работают.

Ответ - создать собственный ViewModifier. В вашем случае я бы упаковал все в один модификатор следующим образом:

struct CircleStyle: ViewModifier {
    @Environment (\.colorScheme) var colorScheme:ColorScheme

    func body(content: Content) -> some View {

    if colorScheme == .light {
        return content
            .foregroundColor(Color(RetroTheme.shared.appMainTint))
            .frame(width: 50, height: 50, alignment: .center)
            .shadow(color: .secondary, radius: 5, x: 0, y: 0)
    } else {
        return content
            .foregroundColor(Color(RetroTheme.shared.appMainTint))
            .frame(width: 50, height: 50, alignment: .center)
    }
}

И использовать это:

Circle()..modifier(CircleStyle())

Если вам нужно добавить больше переменных из вашей модели, просто передайте их в свой модификатор.

SwiftUI позволяет очень просто определить, включен ли темный режим. Нам просто нужно добавить переменную @Enviroment и использовать свойство .colorScheme для сканирования настроек на нашем устройстве и проверки того, включен ли темный режим.

Давайте посмотрим на пример ниже.

      struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        ZStack {
            Color(colorScheme == .light ? .blue : .red)
            Text("Hello, World!")
        }
    }
}

В приведенном выше коде мы создаем переменную @Environment, чтобы увидеть, находится ли наше устройство в темном режиме. Затем внутри нашего вида тела мы устанавливаем цвет фона на красный, если он в темном режиме, или на синий, если он не в темном режиме, используя нашу переменную colorScheme внутри тернарного оператора.

Отличный вариант использования для этого, если вы хотите поддерживать различные пользовательские интерфейсы, когда устройство пользователя находится в темном режиме.

Удачного кодирования;

Другие вопросы по тегам