模糊覆盖不覆盖整个屏幕

Blurred overlay does not cover entire screen

我正在尝试在包含 UITableView 并以模态方式显示的 ViewController 上显示模糊背景。 但我似乎无法获得覆盖整个屏幕的模糊效果,特别是导航栏和状态栏。下面是覆盖导航栏下方区域的模糊效果的屏幕截图,但是不高于它——当我将 UIVisualEffectView 的框架设置为 view.bounds 时会发生这种情况。 (注意:模糊效果设计为与带键盘的标题屏幕同时显示,并且标题屏幕具有清晰的+ non-opaque背景以适应这种模糊效果。)

有趣的是,当我将 UIVisualEffectView 的 frame 设置为 view.frame(而不是 view.bounds)时,模糊效果仅覆盖大约 2/3rds view.bound 覆盖的区域。不确定为什么要这样做。

下面是我的代码。如您所见,按下 'Done' 按钮时,应用会生成 ActionViewController(标题屏幕)以及通过委托方法调用的模糊背景。

@IBAction func donePressed(_ sender: UIButton) {
    let vc = ActionViewController()
    self.definesPresentationContext = true
    self.providesPresentationContextTransitionStyle = true
    vc.modalPresentationStyle = .overFullScreen
    vc.modalTransitionStyle = .coverVertical
    
    self.present(vc, animated: true, completion: nil)
    self.overlayBlurredBackgroundView()
    vc.delegate = self
}

extension PreviewViewController: ActionViewControllerDelegate {
    func overlayBlurredBackgroundView() {
        let blurredBackgroundView = UIVisualEffectView()
        blurredBackgroundView.frame = view.bounds
        blurredBackgroundView.effect = UIBlurEffect(style: .systemThinMaterialDark)
        view.addSubview(blurredBackgroundView)
}

您需要将模糊叠加视图放在呈现的视图控制器中,而不是呈现视图控制器,即 ActionViewController。就frame而言,只需添加右约束,它就会自动布局(无需设置frame),例如,如果您希望模糊视图覆盖整个屏幕,您可以添加这些约束。

ActionViewControllerviewDidLoad函数中调用这个函数

func addOverlayBlurredBackgroundView() {
    let blurView = UIVisualEffectView()
    blurView.effect = UIBlurEffect(style: .systemThinMaterialDark)
    self.view.insertSubview(blurView, at: 0)

    blurView.translatesAutoresizingMaskIntoConstraints = false

    blurView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0.0).isActive = true
    blurView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0.0).isActive = true
    blurView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0.0).isActive = true
    blurView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0.0).isActive = true
}

首先,穆罕默德的建议应该有效。您的代码崩溃的原因可能是您试图在将 blurView 作为子视图添加到您的视图之前先添加约束。关键词是:

they have no common ancestor.

不要那样做。在约束它之前总是添加你的子视图。


最后,实现您想要实现的目标的一种简单方法是,只要在显示透明屏幕(带键盘的屏幕)时切换导航栏的可见性,然后在完成后将导航栏恢复可见.像这样:

func overlayBlurredBackgroundView() {
  self.navigationController?.navigationBar.isHidden = true
  
    let blurredBackgroundView = UIVisualEffectView()
    //blurredBackgroundView.frame = view.bounds
    blurredBackgroundView.effect = UIBlurEffect(style: .systemThinMaterialDark)
    view.addSubview(blurredBackgroundView)
  
    blurredBackgroundView.translatesAutoresizingMaskIntoConstraints = false
    blurredBackgroundView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0.0).isActive = true
    blurredBackgroundView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0.0).isActive = true
    blurredBackgroundView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 0.0).isActive = true
    blurredBackgroundView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 0.0).isActive = true

}

然后在移除时将其放回原处:

func removeBlurredBackgroundView() {
  self.navigationController?.navigationBar.isHidden = false
    for subview in view.subviews {
        if subview.isKind(of: UIVisualEffectView.self) {
            subview.removeFromSuperview()
        }
    }
}