如何将UIBlurEffect与模态视图控制器一起使用?

时间:2014-06-25 04:54:36

标签: ios iphone objective-c user-interface

我有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];
}

6 个答案:

答案 0 :(得分:11)

使用UIVisualEffectView时,您不需要生成快照。尝试删除" - (UIImage *)viewImage"并在模型视图控制器中添加一个大小与视图控制器视图匹配的UIVisualEffectView,并添加所有" control"查看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)
}
}

答案 1 :(得分:9)

在Swift 3中

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

在界面构建器中:

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

在目标VC中,将其设置为第一个视图是设置了AspectToFit的UIImageView,并且对于约束,每边都设置为0-0-0-0。第二个SubView是一个UIBlurView设置为VC的两侧0-0-0-0。 然后将您的元素放在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

答案 2 :(得分:1)

感谢@YarGnawh。这在iOS 8上进行了测试

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

答案 3 :(得分:1)

这是上述答案的组合。

适用于iOS 9.2.1的Xcode 7.2.1(Swift 2.1。)中的Interface builder。

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

在Interface Builder中:

  1. 点击storyboard seque
  2. As" Kind"设置"以模态呈现"
  3. As"演示"设置"过流背景" 注意:在演示文稿viewDidLoad的{​​{1}}中设置第3步将无法正常工作
  4. 请勿忘记点击UIViewController,然后点击UIViewController" - Custom Class将其命名为Class(或任何您想要的内容)。
  5. 代码:

    YOUTransparentModalVC

答案 4 :(得分:1)

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

UIVisualEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];

visualEffectView.frame = self.view.bounds;
self.view insertSubview:visualEffectView atIndex:0];

答案 5 :(得分:0)

查看我的示例项目,我只使用 storyboard 约束来展示模糊效果。

GitHub演示:link