Как замаскировать UIView

Я работаю над приложением, в котором я рисую UIView через код и заполняю его UIColor. Далее я хочу загрузить файл mask.png (без прозрачности, только черно-белый) и замаскировать UIView, чтобы изменить его внешний вид.

есть идеи как это сделать?


person Thomas Joos    schedule 17.06.2010    source источник


Ответы (6)


// Create your mask layer
CALayer* maskLayer = [CALayer layer];
maskLayer.frame = CGRectMake(0,0,yourMaskWidth ,yourMaskHeight);
maskLayer.contents = (__bridge id)[[UIImage imageNamed:@"yourMaskImage.png"] CGImage];

// Apply the mask to your uiview layer        
yourUIView.layer.mask = maskLayer;

Не забудьте импортировать QuartzCore и добавить фреймворк.

#import <QuartzCore/QuartzCore.h>

Это очень просто, но я нигде не нашел ответа!

person JEzu    schedule 08.03.2012
comment
Любой ответ, использующий базовую анимацию вместо базовой графики, должен быть предпочтительным. API CA намного проще понять и использовать. - person zakdances; 24.04.2013

iOS 8 представляет свойство maskView, которое позволяет использовать альтернативный вид для предоставления изображения маски. В Swift:

if let maskImage = UIImage(named: "MaskImage") {
    myView.maskView = UIImageView(image: maskImage)
}

Обратите внимание, что вам нужно предоставить изображение, которое действительно имеет прозрачность; изображение с белыми частями (для непрозрачных) и черными (для прозрачных) работать не будет.

person Robert    schedule 19.03.2015
comment
Есть идеи, почему это может привести к сбою с EXC_BAD_ACCESS? (- [UIImageView _maskView]: сообщение отправлено освобожденному экземпляру) - person Yaroslav; 07.05.2016

Возможно, вы сможете использовать CGContextClipToMask:

-(void) drawRect:(CGRect)dirty {
  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextSaveGState( context );
  CGContextClipToMask( context , [self bounds] , [self maskImage] );
  [super drawRect:dirty]; // or draw your color manually
  CGContextRestoreGState( context );
}
person drawnonward    schedule 17.06.2010

Я создал категорию с приведенным выше кодом:

UIView + ImageMask.h:

#import <UIKit/UIKit.h>

@interface UIView (ImageMask)

- (void) maskWithImage:(UIImage*) mask;
- (void) maskWithImage:(UIImage*)mask size:(CGSize)maskSize;
- (void) removeMask;

@end

UIView + ImageMask.m:

#import <QuartzCore/QuartzCore.h>

#import "UIView+ImageMask.h"

@implementation UIView (ImageMask)

- (void) maskWithImage:(UIImage*) mask {
    [self maskWithImage:mask size:mask.size];
}

- (void) maskWithImage:(UIImage*)mask size:(CGSize)maskSize {
    CALayer* maskLayer = [CALayer layer];
    maskLayer.frame = CGRectMake(0, 0, maskSize.size.width, maskSize.size.height);
    maskLayer.contents = (__bridge id)[mask CGImage];

    // Apply the mask to your uiview layer
    self.layer.mask = maskLayer;
}

- (void) removeMask {
    self.layer.mask = nil;
}

@end
person mt81    schedule 07.07.2013
comment
Какое изображение у вас на входе? черно-белое или полупрозрачное и белое или полупрозрачное и черное? - person Vassily; 20.02.2014
comment
Я использовал черное изображение с альфой. Но я не думаю, что это будет иметь значение. Если попробуете, дайте знать :). - person mt81; 21.02.2014
comment
Я пытался. На самом деле есть разница. Только альфа-компонент будет иметь эффект - person Arsynth; 27.02.2014
comment
да, изображение должно быть PNG с альфа-компонентом. будет замаскирована только альфа, остальные могут быть белыми или черными, не имеет значения - person Vassily; 28.02.2014

Спасибо, обращено вперед,

закончился этой функцией:

- (UIImage*) maskImage:(UIView *)image withMask:(UIImage *)maskImage {

    UIGraphicsBeginImageContext(image.bounds.size);
    [image.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();


    CGImageRef maskRef = maskImage.CGImage; 

    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                        CGImageGetHeight(maskRef),
                                        CGImageGetBitsPerComponent(maskRef),
                                        CGImageGetBitsPerPixel(maskRef),
                                        CGImageGetBytesPerRow(maskRef),
                                        CGImageGetDataProvider(maskRef), NULL, false);

    CGImageRef masked = CGImageCreateWithMask([viewImage CGImage], mask);
    return [UIImage imageWithCGImage:masked];

}
person Thomas Joos    schedule 17.06.2010

Swift 2.0

Передайте этой функции UIImage и изображение маски, и вы получите изображение с маской как UIImage.

func maskImage(image:UIImage, mask:(UIImage))->UIImage{

    let imageReference = image.CGImage
    let maskReference = mask.CGImage

    let imageMask = CGImageMaskCreate(CGImageGetWidth(maskReference),
                                  CGImageGetHeight(maskReference),
                                  CGImageGetBitsPerComponent(maskReference),
                                  CGImageGetBitsPerPixel(maskReference),
                                  CGImageGetBytesPerRow(maskReference),
                                  CGImageGetDataProvider(maskReference), nil, true)

   let maskedReference = CGImageCreateWithMask(imageReference, imageMask)

   let maskedImage = UIImage(CGImage:maskedReference!)

   return maskedImage
}
person Ashutosh Jha    schedule 20.04.2016