iOS中如何实现UIView镂空效果-创新互联

这篇文章将为大家详细讲解有关iOS中如何实现UIView镂空效果,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

员工经过长期磨合与沉淀,具备了协作精神,得以通过团队的力量开发出优质的产品。成都创新互联坚持“专注、创新、易用”的产品理念,因为“专注所以专业、创新互联网站所以易用所以简单”。公司专注于为企业提供网站建设、网站制作、微信公众号开发、电商网站开发,微信小程序开发,软件按需定制开发等一站式互联网企业服务。

这是一种实现UIView镂空效果的方案,可以快速实现任意形状的镂空、文字的镂空、带镂空的毛玻璃效果等。本质上是UIViewmaskView效果。

前言

首先来复习一下遮罩效果的实现。如果我们有一张图片,又恰好有一个圆,当我们把圆设置为图片的遮罩时,会得到这样的结果。

iOS中如何实现UIView镂空效果

代码实现看上去像是这样:

view.maskView = maskView;

那么问题来了,如果我们希望得到下面的结果,该怎么做呢?这看起来像是图层的相减,即原来的图层减去遮罩的部分。

iOS中如何实现UIView镂空效果

可惜苹果爸爸不够贴心,没有提供方便的接口调用。让我们来看看可以怎么实现。

一、思路

我们的最终目标是,封装出一个接口,调用方式类似于maskView属性,可以很方便地对一个UIView做镂空效果。

注:以下用originView指代需要上效果的view,用maskView指代充当遮罩的view

目前看来,可以从两个方向入手:

  1. 修改遮罩的绘制过程

  2. 修改 maskView 本身

方式一是指,在设置这个属性的时候,对originView的视图进行重新绘制,然后在绘制的时候,减掉maskView的区域。

方式二是指,当拿到maskView的时候,先对maskView本身先进行处理,将遮罩范围取反。然后再做遮罩效果,由于遮罩的区域已经相反,于是得到的结果也是相反的,就达到镂空的目的。

看上去方式二比较靠谱,而且最后是调用UIViewsetMaskView:来实现,还可以保留原来遮罩的一些特性。比如当修改maskViewframe的时候,originView的遮罩位置也会相应改变。

二、实现

生成相反的遮罩图可以分为三步。假设一开始拿到的maskView是下面这样,让我们来看下,转换过程中遮罩图每一步的变化。

iOS中如何实现UIView镂空效果

注:为了更直观的效果,图片中透明的部分用灰白相间格子来表示(以下相同)。

1、将maskView转化为UIImage

UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
CGContextTranslateCTM(UIGraphicsGetCurrentContext(),
           view.frame.origin.x,
           view.frame.origin.y);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

这一步拿到了maskView对应的image图像。此时遮罩图的大小会被同步为originView的大小。

iOS中如何实现UIView镂空效果2、将

UIImage转换为只有alpha通道的CGContextRef

CGImageRef originalMaskImage = [image CGImage];
float width = CGImageGetWidth(originalMaskImage);
float height = CGImageGetHeight(originalMaskImage);
  
int strideLength = ROUND_UP(width * 1, 4);
unsigned char * alphaData = calloc(strideLength * height, sizeof(unsigned char));
CGContextRef alphaOnlyContext = CGBitmapContextCreate(alphaData,
                           width,
                           height,
                           8,
                           strideLength,
                           NULL,
                           kCGImageAlphaOnly);
  
CGContextDrawImage(alphaOnlyContext, CGRectMake(0, 0, width, height), originalMaskImage);

这时候的alphaOnlyContext对应的图像是下面这样,只保留了alpha通道。

iOS中如何实现UIView镂空效果3、将

CGContextRef中的alpha值进行遍历转换

for (int y = 0; y < height; y++) {
  for (int x = 0; x < width; x++) {
    unsigned char val = alphaData[y*strideLength + x];
    val = 255 - val;
    alphaData[y*strideLength + x] = val;
  }
}
  
CGImageRef alphaMaskImage = CGBitmapContextCreateImage(alphaOnlyContext);
UIImage *result = [UIImage imageWithCGImage:alphaMaskImage];

转换后,获得的result图像是:

iOS中如何实现UIView镂空效果

于是,我们就可以用result愉快地进行mask了。

三、使用

我们可以将上述的步骤,封装为一个方法,用category来实现。

@interface UIView (MFSubtractMask)
- (void)setSubtractMaskView:(UIView *)view;
- (UIView *)subtractMaskView;
@end

这样调用起来就十分方便了,一行代码搞定:

view.subtractMaskView = maskView;

四、局限性

1.subtractMaskView不会自动刷新

我们知道,当UIViewmaskView的内容动态修改时,会实时反映到UIView中。但在本项目中,subtractMaskView属性会生成一张全新的图片来作为遮罩图,因为不会根据subtractMaskView的内容实时来刷新视图。如果需要更新,必须手动调用setSubtractMaskView:方法来重新生成遮罩图。

2.setSubtractMaskView:不宜被频繁调用

setSubtractMaskView:本质上是生成一个新的遮罩图的过程,该过程涉及图片像素的遍历转换,较为耗时,不宜频繁调用。

综上所述,这种方案适合只生成一次遮罩图的场景。

关于“iOS中如何实现UIView镂空效果”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

另外有需要云服务器可以了解下创新互联建站www.cdcxhl.com,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享标题:iOS中如何实现UIView镂空效果-创新互联
分享地址:http://myzitong.com/article/djpogj.html