模态跳转至另一个ViewController后为原ViewController添加模糊效果
实现方案:无需自定义转场即可切换模糊效果
当然可以!完全不需要自定义转场就能实现这个需求,下面是两种简单可行的实现方式,步骤清晰易操作:
前提准备
首先确保你已经完成了这些基础设置:
- VC1中已创建好覆盖整个视图的
UIVisualEffectView,并将其声明为类属性(方便后续修改效果) - VC2的
modalPresentationStyle设置为.overCurrentContext,且view.backgroundColor = .clear
方式一:利用闭包回调(推荐,耦合度低)
这种方式通过在VC2中添加回调闭包,在VC2展示完成后通知VC1切换模糊效果:
第一步:在VC2中定义回调闭包
class VC2: UIViewController { // 定义展示完成的回调 var didAppearHandler: (() -> Void)? // 定义消失完成的回调(可选,用于恢复VC1的效果) var didDisappearHandler: (() -> Void)? override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // 触发展示完成的回调 didAppearHandler?() } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) // 触发消失完成的回调,恢复VC1的效果 didDisappearHandler?() } }
第二步:在VC1中配置Segue并绑定回调
class VC1: UIViewController { // 声明为类属性,方便后续修改效果 private var backgroundEffectView: UIVisualEffectView! override func viewDidLoad() { super.viewDidLoad() // 初始化视觉效果视图(初始无效果) backgroundEffectView = UIVisualEffectView(effect: nil) backgroundEffectView.frame = view.bounds backgroundEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // 插入到视图底层,避免遮挡其他控件 view.insertSubview(backgroundEffectView, at: 0) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard segue.identifier == "ShowVC2Segue", let vc2 = segue.destination as? VC2 else { return } // 绑定展示完成的回调:切换为模糊效果 vc2.didAppearHandler = { [weak self] in // 添加动画,让过渡更自然 UIView.animate(withDuration: 0.3) { self?.backgroundEffectView.effect = UIBlurEffect(style: .systemMaterial) } } // 绑定消失完成的回调:恢复无效果(可选) vc2.didDisappearHandler = { [weak self] in UIView.animate(withDuration: 0.3) { self?.backgroundEffectView.effect = nil } } } }
方式二:利用系统通知(适合不需要直接关联VC的场景)
通过监听系统的视图控制器展示/消失通知,来触发效果切换:
class VC1: UIViewController { private var backgroundEffectView: UIVisualEffectView! override func viewDidLoad() { super.viewDidLoad() // 初始化视觉效果视图 backgroundEffectView = UIVisualEffectView(effect: nil) backgroundEffectView.frame = view.bounds backgroundEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.insertSubview(backgroundEffectView, at: 0) // 监听展示和消失通知 NotificationCenter.default.addObserver( self, selector: #selector(handleVC2Presentation), name: UIViewController.didShowNotification, object: nil ) NotificationCenter.default.addObserver( self, selector: #selector(handleVC2Dismissal), name: UIViewController.didDismissNotification, object: nil ) } @objc private func handleVC2Presentation(notification: Notification) { // 判断展示的是VC2 guard let presentedVC = notification.object as? VC2, presentedVC == presentedViewController else { return } // 切换为模糊效果 UIView.animate(withDuration: 0.3) { self.backgroundEffectView.effect = UIBlurEffect(style: .systemMaterial) } } @objc private func handleVC2Dismissal(notification: Notification) { // 判断消失的是VC2 guard let dismissedVC = notification.object as? VC2 else { return } // 恢复无效果 UIView.animate(withDuration: 0.3) { self.backgroundEffectView.effect = nil } } // 记得在销毁时移除通知 deinit { NotificationCenter.default.removeObserver(self) } }
关键注意点
- 一定要给效果切换加上
UIView.animate动画,让模糊效果的变化和模态转场的动画同步,避免突兀感 - 如果需要在VC2消失后恢复VC1的视觉效果,不要忘记实现对应的回调或通知处理
- 确保
backgroundEffectView被添加到VC1视图的底层(insertSubview(at: 0)),避免遮挡VC1上的其他控件
内容的提问来源于stack exchange,提问作者Tigran Iskandaryan
相关产品推荐
相关产品推荐

