用户可以在应用程序设置的某一部分中切换主题,如下所示。
这是通过更改
window.overrideUserInterfaceStyle
来完成的。
虽然它按预期工作,但更改根本没有动画。整个应用程序会立即转到所选样式,而不是 iOS 设置应用程序中的平滑更改。
仅仅将作业放在
completion
的UIView.animate(withDuration duration: TimeInterval, animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil)
中是行不通的。
有一种简单的方法可以用动画更改应用程序暗模式主题
Swift 5(更新):
if let window = UIApplication.shared.windows.first {
UIView.transition (with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
window.overrideUserInterfaceStyle = .dark //.light or .unspecified
}, completion: nil)
}
斯威夫特 4:
if let window = UIApplication.shared.keyWindow {
UIView.transition (with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
window.overrideUserInterfaceStyle = .dark //.light or .unspecified
}, completion: nil)
}
您可以执行以下操作:
var toggleVar = true
@IBAction func buttonDidTap(_ sender: UIButton) {
UIView.animate(withDuration: 0.5, animations: {
self.overrideUserInterfaceStyle = self.toggleVar ? .dark : .light
self.view.backgroundColor = .systemBackground
}) { (_) in
//set overrideUserInterfaceStyle app wide
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = self.overrideUserInterfaceStyle
self.toggleVar.toggle()
}
}
因此,为了使背景变化动画化,您需要动画化
self.view.backgroundColor = .systemBackground
。在完成处理程序中,您可以为整个应用程序设置新的 overrideUserInterfaceStyle
...
我也有同样的问题。在尝试使用
UIView/UIWindow.animate/transition
和动画选项但无果后,我按如下方式解决了该问题:
假设您还在 UINavigationController 中使用 UITableViewController,例如:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Disable all checkmarks
tableView.visibleCells.forEach { (cell) in
cell.accessoryType = .none
}
// Set checkmark
let cell = tableView.cellForRow(at: indexPath)
cell?.accessoryType = .checkmark
// Capture and add screenshot of current screen
let imageView = UIImageView()
imageView.image = UIApplication.shared.makeSnapshot()
imageView.addTo(self.navigationController!.view).snp.makeConstraints { (maker) in
maker.edges.equalToSuperview()
}
// Set new dark mode setting and fade out screenshot
UIView.animate(withDuration: 0.5, animations: {
// Important to set it within the animations closure, so that the status bar will animate
UIApplication.shared.windows.first?.overrideUserInterfaceStyle = .dark
imageView.alpha = 0
}) { (_) in
imageView.removeFromSuperview()
}
// Deselect row
tableView.deselectRow(at: indexPath, animated: true)
}
备注:
makeSnapshot()
方法来自这篇文章:https://stackoverflow.com/a/40953026/4489859.dark
更改为您项目的正确动态值结果:
在设备本身上,对我来说比系统的变化动画还要流畅!
我使用 Xamarin,对我来说解决方案是:
UIView TempView = Window.SnapshotView(true);
Window.Add(TempView);
Window.OverrideUserInterfaceStyle = UIUserInterfaceStyle.Light;
UIView.Animate(0.5,
() => {
TempView.Alpha = 0;
},
() => {
TempView.RemoveFromSuperview();
TempView.Dispose();
});
斯威夫特5
@objc func changeStyleHandler() {
guard let window = UIApplication.shared.windows.first else { return }
let newInterfaceStyle: UIUserInterfaceStyle = (traitCollection.userInterfaceStyle == .dark) ? .light : .dark
UIView.transition (with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
window.overrideUserInterfaceStyle = newInterfaceStyle
}, completion: nil)
}