如何在 SwiftUI 中提供“系统”外观选择?
Posted
技术标签:
【中文标题】如何在 SwiftUI 中提供“系统”外观选择?【英文标题】:How to provide a ‘System’ appearance choice in SwiftUI? 【发布时间】:2020-10-31 07:55:50 【问题描述】:主要问题
抱歉,标题太长了。我正在尝试弄清楚如何为用户提供将应用程序的 ColorScheme 设置为“系统”的选择。
同样,让应用程序默认为系统的暗模式/亮模式。我知道 UIKit 有办法将样式设置为 .unspecified 但我不确定如何在 SwiftUI 中访问它。
我已经尝试将 .preferredColor()
设置为 nil,它有点工作,但有时它没有。我是 Swift 管理状态的新手,所以我肯定做错了什么。
附带问题:
当我将.preferredColor()
设置为.dark
时,我的模态设置表没有更新?它始终保持系统颜色。我在 ...App.swift 文件中的 ContentView()
上触发了 .preferredColor()
。
更新
我也解决了我的附带问题,只需将.preferredColor()
添加到模态表即可。这并不理想,但确实有效。但是我仍然无法弄清楚如何在 SwiftUI 中设置 .system
首选项
【问题讨论】:
【参考方案1】:我最终找到了解决这个问题的两种方法。第一个是jinjie 发现的,另一个是我发现的。两种解决方案都可以是viewed here - repo。由rizwankce创建。
解决方案
我最终做的是使用包Introspect 从我使用ViewModifier
的主视图中获取UIViewController
。
在ViewModifier
中,我只使用了.introspectViewController
,这给了我UIViewController
,这样我就可以像这样设置UIViewController.overrideUserInterfaceStyle = .unspecified
。然后我只是根据下面没有看到的Picker
有条件地执行此操作。 ⤵
/// All themes
enum Themes: String
case Dark
case Light
case System
// MARK: - Theme Switch
struct ThemeSwitch: ViewModifier
let appStorage: String
func body(content: Content) -> some View
content
.introspectViewController UIViewController in
switch appStorage
case Themes.System.rawValue: UIViewController.overrideUserInterfaceStyle = .unspecified
case Themes.Dark.rawValue: UIViewController.overrideUserInterfaceStyle = .dark
case Themes.Light.rawValue: UIViewController.overrideUserInterfaceStyle = .light
default: UIViewController.overrideUserInterfaceStyle = .unspecified
// MARK: - Extensions
extension View
func themeSwitch(appStorage: String) -> some View
modifier(ThemeSwitch(appStorage: appStorage))
我只是将所需主题作为字符串存储到 @State
对象中,该对象还更新了 @AppStorage
对象,因此无论如何应用程序始终可以选择。
您不必使用 Introspect,而是可以创建自己的包装器,但我已经安装了这个包,所以我想为什么不这样做。
替代解决方案
另一种解决方案是制作视图修改器并有条件地显示修改后的视图。条件基于ColorScheme
类型的可选数组、字典等。如果它不是 nil,它要么解开可选项,要么只显示未修改的视图。你可以在 repo 中找到它。上面提到的已关闭问题或拉取请求。
希望将来 Apple 会提供一种本地方式来实现这一点,但现在可以做到!如果出现更好的情况,我会尝试在将来更新此答案。
【讨论】:
以上是关于如何在 SwiftUI 中提供“系统”外观选择?的主要内容,如果未能解决你的问题,请参考以下文章
iOS14中点击SwiftUI列表项导航跳转返回后外观呈灰色的解决
SwiftUI List 在 Sheet 中的外观和行为与在 NavigationLink 中不同
如何在 SwiftUI WidgetKit 占位符中自定义占位符外观?
SwiftUI 4.0 实现朴素(Plain)的 Form 样式