Lil*_*aen 15 ios swift swiftui ios-darkmode
我目前正在我的应用程序中研究暗模式。虽然由于我的 SwiftUI 基础,暗模式本身并没有太大的困难,但我正在努力选择将 ColorScheme 设置为独立于系统 ColorScheme 的选项。
我在苹果人机界面指南中找到了这个,我想实现这个功能。(链接:人机界面指南)
知道如何在 SwiftUI 中做到这一点吗?我发现了一些@Environment
关于这个主题的提示,但没有进一步的信息。(链接:最后一段)
Moj*_*ini 28
要更改单个视图的配色方案(可能是ContentView
应用程序的主视图),您可以使用以下修饰符:
.environment(\.colorScheme, .light) // or .dark
Run Code Online (Sandbox Code Playgroud)
或者
.preferredColorScheme(.dark)
Run Code Online (Sandbox Code Playgroud)
此外,您可以将其ContentView
应用到 使您的整个应用程序变暗!
假设您没有更改ContentView
场景委托中的名称或@main
UIKit
部分和SwiftUI
)首先,您需要访问窗口以更改UserInterfaceStyle
在UIKit
.
我在SceneDelegate
:
private(set) static var shared: SceneDelegate?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
Self.shared = self
...
}
Run Code Online (Sandbox Code Playgroud)
然后你需要将一个动作绑定到切换。所以你需要一个模型。
struct ToggleModel {
var isDark: Bool = true {
didSet {
SceneDelegate.shared?.window!.overrideUserInterfaceStyle = isDark ? .dark : .light
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后,您只需要切换开关:
struct ContentView: View {
@State var model = ToggleModel()
var body: some View {
Toggle(isOn: $model.isDark) {
Text("is Dark")
}
}
}
Run Code Online (Sandbox Code Playgroud)
每个人UIView
都可以访问窗口,因此您可以使用它来将. overrideUserInterfaceStyle
值设置为您需要的任何方案。
myView.window?.overrideUserInterfaceStyle = .dark
Run Code Online (Sandbox Code Playgroud)
@AppStorage
使用切换深色模式的demo
PS:对于全局切换,需要在WindowGroup/MainContentView上添加修饰符
import SwiftUI
struct SystemColor: Hashable {
var text: String
var color: Color
}
let backgroundColors: [SystemColor] = [.init(text: "Red", color: .systemRed), .init(text: "Orange", color: .systemOrange), .init(text: "Yellow", color: .systemYellow), .init(text: "Green", color: .systemGreen), .init(text: "Teal", color: .systemTeal), .init(text: "Blue", color: .systemBlue), .init(text: "Indigo", color: .systemIndigo), .init(text: "Purple", color: .systemPurple), .init(text: "Pink", color: .systemPink), .init(text: "Gray", color: .systemGray), .init(text: "Gray2", color: .systemGray2), .init(text: "Gray3", color: .systemGray3), .init(text: "Gray4", color: .systemGray4), .init(text: "Gray5", color: .systemGray5), .init(text: "Gray6", color: .systemGray6)]
struct DarkModeColorView: View {
@AppStorage("isDarkMode") var isDarkMode: Bool = true
var body: some View {
Form {
Section(header: Text("Common Colors")) {
ForEach(backgroundColors, id: \.self) {
ColorRow(color: $0)
}
}
}
.toolbar {
ToolbarItem(placement: .principal) { // navigation bar
Picker("Color", selection: $isDarkMode) {
Text("Light").tag(false)
Text("Dark").tag(true)
}
.pickerStyle(SegmentedPickerStyle())
}
}
.modifier(DarkModeViewModifier())
}
}
private struct ColorRow: View {
let color: SystemColor
var body: some View {
HStack {
Text(color.text)
Spacer()
Rectangle()
.foregroundColor(color.color)
.frame(width: 30, height: 30)
}
}
}
public struct DarkModeViewModifier: ViewModifier {
@AppStorage("isDarkMode") var isDarkMode: Bool = true
public func body(content: Content) -> some View {
content
.environment(\.colorScheme, isDarkMode ? .dark : .light)
.preferredColorScheme(isDarkMode ? .dark : .light) // tint on status bar
}
}
struct DarkModeColorView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
DarkModeColorView()
}
}
}
Run Code Online (Sandbox Code Playgroud)
@ADB 的答案很好,但我找到了更好的答案。希望有人找到比我更好的:D 一旦应用程序切换状态(进入后台并返回),这种方法不会一遍又一遍地调用相同的函数
在你@main
看来添加:
ContentView()
.modifier(DarkModeViewModifier())
Run Code Online (Sandbox Code Playgroud)
现在创建DarkModeViewModifier()
视图模型:
class AppThemeViewModel: ObservableObject {
@AppStorage("isDarkMode") var isDarkMode: Bool = true // also exists in DarkModeViewModifier()
@AppStorage("appTintColor") var appTintColor: AppTintColorOptions = .indigo
}
struct DarkModeViewModifier: ViewModifier {
@ObservedObject var appThemeViewModel: AppThemeViewModel = AppThemeViewModel()
public func body(content: Content) -> some View {
content
.preferredColorScheme(appThemeViewModel.isDarkMode ? .dark : appThemeViewModel.isDarkMode == false ? .light : nil)
.accentColor(Color(appThemeViewModel.appTintColor.rawValue))
}
}
Run Code Online (Sandbox Code Playgroud)
小智 7
使用@AppStorage
初始应用程序启动代码
确保appearanceSwitch是一个可选的ColorScheme?所以.none不能被选择
import SwiftUI
@main
struct AnOkApp: App {
@AppStorage("appearanceSelection") private var appearanceSelection: Int = 0
var appearanceSwitch: ColorScheme? {
if appearanceSelection == 1 {
return .light
}
else if appearanceSelection == 2 {
return .dark
}
else {
return .none
}
}
var body: some Scene {
WindowGroup {
AppearanceSelectionView()
.preferredColorScheme(appearanceSwitch)
}
}
}
Run Code Online (Sandbox Code Playgroud)
选择视图
import SwiftUI
struct AppearanceSelectionView: View {
@AppStorage("appearanceSelection") private var appearanceSelection: Int = 0
var body: some View {
NavigationView {
Picker(selection: $appearanceSelection) {
Text("System")
.tag(0)
Text("Light")
.tag(1)
Text("Dark")
.tag(2)
} label: {
Text("Select Appearance")
}
.pickerStyle(.menu)
}
}
}
Run Code Online (Sandbox Code Playgroud)
@Mojtaba Hosseini 的回答确实帮助了我,但我使用的是 iOS14@main
而不是SceneDelegate
,以及一些UIKit
视图,所以我最终使用了这样的东西(这不会切换模式,但它确实设置了暗模式SwiftUI
和UIKit
:
@main
struct MyTestApp: App {
@Environment(\.scenePhase) private var phase
var body: some Scene {
WindowGroup {
ContentView()
.accentColor(.red)
.preferredColorScheme(.dark)
}
.onChange(of: phase) { _ in
setupColorScheme()
}
}
private func setupColorScheme() {
// We do this via the window so we can access UIKit components too.
let window = UIApplication.shared.windows.first
window?.overrideUserInterfaceStyle = .dark
window?.tintColor = UIColor(Color.red)
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7056 次 |
最近记录: |