如何在 iOS 中以动画方式更改暗模式?

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

用户可以在应用程序设置的某一部分中切换主题,如下所示。

这是通过更改

window.overrideUserInterfaceStyle
来完成的。

虽然它按预期工作,但更改根本没有动画。整个应用程序会立即转到所选样式,而不是 iOS 设置应用程序中的平滑更改。

仅仅将作业放在

completion
UIView.animate(withDuration duration: TimeInterval, animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil)
中是行不通的。

app setting

ios swift
5个回答
19
投票

有一种简单的方法可以用动画更改应用程序暗模式主题

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)
}

1
投票

您可以执行以下操作:

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
...


0
投票

我也有同样的问题。在尝试使用

UIView/UIWindow.animate/transition
和动画选项但无果后,我按如下方式解决了该问题:

  • 捕捉整个屏幕
  • 使用捕获的图像添加全屏 UIImageView
  • 在后台切换用户界面风格(不动画)
  • 淡出 UIImageView

假设您还在 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)
}

备注:

结果:

在设备本身上,对我来说比系统的变化动画还要流畅!


0
投票

我使用 Xamarin,对我来说解决方案是:

UIView TempView = Window.SnapshotView(true);    

Window.Add(TempView);

Window.OverrideUserInterfaceStyle = UIUserInterfaceStyle.Light;

UIView.Animate(0.5,
() => { 
    TempView.Alpha = 0;
},
() => {
    TempView.RemoveFromSuperview();
    TempView.Dispose();
});

0
投票

斯威夫特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)
    
}
© www.soinside.com 2019 - 2024. All rights reserved.