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

13 iphone user-interface objective-c ios

我有一个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;
}
Run Code Online (Sandbox Code Playgroud)

在模态视图控制器中:

- (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];
}
Run Code Online (Sandbox Code Playgroud)

Yar*_*awh 11

使用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];
}
Run Code Online (Sandbox Code Playgroud)

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: {})
}
}
Run Code Online (Sandbox Code Playgroud)

这是模态

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)
}
}
Run Code Online (Sandbox Code Playgroud)

  • @ProgramGuy检查上面的更新代码.做记录!`modal.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext` (6认同)

Yun*_*Dai 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
        }

}
Run Code Online (Sandbox Code Playgroud)

然后在我的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

    }
}
Run Code Online (Sandbox Code Playgroud)

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

// 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
        })
    }
Run Code Online (Sandbox Code Playgroud)

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

希望这可以帮助!

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

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