How do I (successfully) set a maskView to a UIView

2019-02-23 06:45发布

问题:

I'm making a camera-based app and would like to make a frosted overlay on the camera preview, with a rounded rectangle cut out from the frosted view.

I've been trying to achieve this with the maskLayer of UIView, introduced with iOS 8 and have been wildly unsuccessful.

Here's what my code currently looks like:

// Blur the preview
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIView *blurView = [[UIVisualEffectView alloc] initWithEffect:effect];
blurView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view insertSubview:blurView aboveSubview:imagePicker.view];

// Make blur view fill screen
{
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[blurView]-0-|"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:NSDictionaryOfVariableBindings(blurView)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[blurView]-0-|"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:NSDictionaryOfVariableBindings(blurView)]];
}

// Add a rounded of transparency to the blurView  **not working**
UIView *mask = [[UIView alloc] initWithFrame:CGRectMake(50.f, 50.f, 50.f, 50.f)];
mask.alpha = 1.0f;
mask.backgroundColor = [UIColor redColor];
[blurView setMaskView:mask]; // Remove this line, and everything is frosted.  Keeping this line and nothing is frosted. 

As my comments indicate, adding the mask removes the frosted view completely (changing the opacity of the mask does nothing). I know that this won't create the effect I'm looking for (it should only be frosted in that rectangle), but I can't get the maskView to work in any capacity.

回答1:

The UIView api says

An optional view whose alpha channel is used to mask a view’s content.

The best way to see this is to use a UIImageView loaded with an RGBA image that sports an alpha channel - a PNG exported with transparency switched on from photoshop will do it. And then resize, with the origin set to 0,0.

A second way to do it would be to create a UIView, with no alpha i.e. [UIColor clearColor] and add a subview which has an alpha [UIColor whiteColor];

UIView *mask = [[UIView alloc] initWithFrame:(CGRect){0,0,100,100}];
mask.backgroundColor = [UIColor clearColor];
UIView *areaToReveal = [[UIView alloc] initWithFrame:(CGRect){20,20,50,50}];
areaToReveal.backgroundColor = [UIColor whiteColor];
[mask addSubview:areaToReveal];
_myView.maskView = mask;

You could add further UIViews which are translucent by x amount using [UIColor colorFromRed: green: blue: alpha:x];