如何在模态视图控制器中使用UIBlurEffect?

我有一个UIViewController ,以模态方式呈现另一个UIViewController 。 我希望模态视图控制器具有iOS 7引入的模糊/透明度。 我尝试使用新的UIVisualEffect但它似乎只适用于UIViews ,而不是UIViewControllers

这是我编写的代码,我作为子视图添加的所有视图都是我想要在用户界面中的下方模糊视图上方。

在呈现视图控制器中,我在应用模糊之前拍摄了我传递给模态视图控制器的屏幕截图。

在呈现视图控制器中:

 - (UIImage *)viewImage { CGSize size = CGSizeMake(self.view.frame.size.width,self.view.frame.size.height); UIGraphicsBeginImageContext(size); [self.view drawViewHierarchyInRect:(CGRect){CGPointZero, self.view.frame.size.width, self.view.frame.size.height} afterScreenUpdates:YES]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } 

在模态视图控制器中:

 - (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:[[UIImageView alloc] initWithImage:self.backgroundImage]]; //self.backgroundImage is the image that the method above returns, it's a screenshot of the presenting view controller. UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; [blurEffectView setFrame:self.view.bounds]; [self.view addSubview:blurEffectView]; [self.view bringSubviewToFront:self.cancelButton]; [self.view bringSubviewToFront:self.titleLabel]; [self.view bringSubviewToFront:self.tableView]; } 

使用UIVisualEffectView时,您不需要生成快照。 尝试删除“ – (UIImage *)viewImage”并在模型视图控制器中添加一个大小与视图控制器视图匹配的UIVisualEffectView,并将所有“控制”视图添加到UIVisualEffectView的contentView中。

 - (void)viewDidLoad { [super viewDidLoad]; UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; [blurEffectView setFrame:self.view.bounds]; [self.view addSubview:blurEffectView]; [blurEffectView.contentView addSubview:self.cancelButton]; [blurEffectView.contentView addSubview:self.titleLabel]; [blurEffectView.contentView addSubview:self.tableView]; } 

https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIVisualEffectView/index.html

我没有尝试过故事板,但这是一个经过测试的工作片段。 可能是一个好的开始。 转换为objc应该是非常直接的

这是呈现视图控制器

 import UIKit class BaseViewController: UIViewController { init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } override func viewDidLoad() { super.viewDidLoad() var backgroundImage = UIImageView(image: UIImage(named: "image")) self.view.addSubview(backgroundImage) var button = UIButton(frame: CGRectMake(0, 100, 320, 50)) button.setTitle("Lorem Ipsum", forState: UIControlState.Normal) button.backgroundColor = UIColor.redColor() button.addTarget(self, action: "onButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside) self.view.addSubview(button) } func onButtonTapped(sender: UIButton?) { var modal = ModalViewController(nibName: nil, bundle: nil) modal.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext self.presentViewController(modal, animated: true, completion: {}) } } 

这是模态

 import UIKit class ModalViewController: UIViewController { init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.clearColor() let effect = UIBlurEffect(style: UIBlurEffectStyle.Light) let blurView = UIVisualEffectView(effect: effect) blurView.frame = self.view.bounds self.view.addSubview(blurView) } } 

在Swift 3中

我发现如果你正在进行一个模态转换到一个新的UIViewController并将它放在具有清晰背景的上下文中,那么你可以看到最后一个VC。 在IB中使用UIVisualEffect视图设置无法正常工作。 您将获得的是在新视图演示结束时呈现的模糊。

在界面构建器中:

建立一个模态segue到另一个视图,使种类:呈现模态,过渡:交叉淡入淡出。 然后给它一个像“showMainMenu”这样的标识符。

在目标VC中,将其设置为第一个视图是设置了AspectToFit的UIImageView,并且对于约束,每边都设置为0-0-0-0。 第二个SubView是一个UIBlurView设置为0-0-0-0到VC的两侧。 然后将您的元素放在UIBlurView的顶部,就像很好的对比文本一样。

为背景创建一个var,以设置为您将要进行的VC的UIImageView。

var background:UIImage! = UIImage()

现在运行segue你会注意到模糊弹出并且看起来很糟糕。

要解决此问题,请编写一些代码以使用此扩展代码为UIImage拍摄快照

  extension UIImage { class func takeScreenshot(view: UIView) -> UIImage? { // Create screenshot UIGraphicsBeginImageContext(view.bounds.size) view.layer.render(in: UIGraphicsGetCurrentContext()!) let screenshot:UIImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() print("Taking Screenshot") UIGraphicsEndImageContext() return screenshot } } 

然后在我的segue中我做了以下事情:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "showMainMenu" { let vc = segue.destination as! MainViewController // I am using a VERY long scroll view so self.view.window! ensures that you only take a picture of your actual view instead of a view that is longer than your screen size. let screenshot: UIImage = UIImage.takeScreenshot(view: self.view.window!)! vc.background = screenshot } } 

一旦被激活,在新的视图控制器中确保你运行它。

 // set the image over to the background image. override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.backgroundImage.image = background } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // prevent the blurView for just popping in due to the segue UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveEaseInOut, animations: { // make the background transparent so you can now see what is beneath that layer. self.backgroundImage.alpha = 0 }) } 

这样你就可以在没有太多代码的情况下获得甜蜜的模态IB淡入! 此外,如果您在当前VC下方的最后一个VC上有移动元素,则可以在模糊下看到它。

希望这可以帮助!

随便在我的git中结帐一个示范项目!

https://github.com/yungdai/Smooth-blur-transition-using-storyboard

感谢@YarGnawh。 这在iOS 8上测试过

 UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; [blurEffectView setFrame:self.view.bounds]; self.tableView.backgroundView = blurEffectView; 

这是上述答案的组合。

这适用于iOS 9.2.1的Xcode 7.2.1(Swift 2.1。)中的Interface构建器。

代码已在模拟器和设备上进行了测试。

在Interface Builder中:

  1. 单击storyboard seque
  2. 作为“善良”设置“当前模态”
  3. 当“Presentation”设置“Over Current Context”时注意:在viewDidLoad中设置呈现UIViewController第3步将不起作用
  4. 别忘了单击你的UIViewController并在Custom Class下 – Class名称YOUTransparentModalVC (或任何你想要的)。

在代码中:

 import UIKit let IMAGE_OVERLAY_NAME = "backgroundColorExample" class YOUTransparentModalVC: UIViewController { private var backgroundImageOverlayIV:UIImageView! override func viewDidLoad() { super.viewDidLoad() self.setupTransparentView() self.setupDissmissingVCOnTap() self.setupBackgroudImage() } private func setupTransparentView() { self.view.backgroundColor = UIColor.clearColor() let effect = UIBlurEffect(style: UIBlurEffectStyle.Light) let blurView = UIVisualEffectView(effect: effect) blurView.frame = self.view.bounds self.view.addSubview(blurView) } private func setupBackgroudImage() { self.backgroundImageOverlayIV = UIImageView(frame: self.view.frame) self.backgroundImageOverlayIV.image = UIImage(named: IMAGE_OVERLAY_NAME) self.view.addSubview(self.backgroundImageOverlayIV) } private func setupDissmissingVCOnTap() { let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissVC") view.addGestureRecognizer(tap) } func dismissVC() { self.dismissViewControllerAnimated(true, completion: nil) } } 

最简单的方法是在viewDidLoad中复制并粘贴此代码:)

 UIVisualEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; visualEffectView.frame = self.view.bounds; self.view insertSubview:visualEffectView atIndex:0]; 

看看我的示例项目,我只使用故事板约束来演示模糊效果。

GitHub演示: 链接