iOS中一行代码实现 UIView 镂空效果

iOS中一行代码实现 UIView 镂空效果,第1张

概述iOS中一行代码实现 UIView 镂空效果 这是一种实现 UIView 镂空效果的方案,可以快速实现任意形状的镂空.文字的镂空.带镂空的毛玻璃效果等.本质上是 UIView 的 maskView 效果. 前言 首先来复习一下遮罩效果的实现.如果我们有一张图片,又恰好有一个圆,当我们把圆设置为图片的遮罩时,会得到这样的结果. 代码实现看上去像是这样: view.maskView = maskView; 那么问题来了,如果我们希望得到下面的结果,该怎么做呢?这看起来像是图层的相减,即原来的图层减去遮罩的部分. 可惜苹果爸爸不够贴心,没有提供方


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

前言

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


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

vIEw.maskVIEw = maskVIEw;

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


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

一、思路

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

注:以下用 originVIEw 指代需要上效果的 vIEw ,用 maskVIEw 指代充当遮罩的 vIEw

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

修改遮罩的绘制过程修改 maskVIEw 本身

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

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

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

二、实现

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


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

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 的大小。


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,height),originalMaskImage);

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


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 图像是:


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

三、使用

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

@interface UIVIEw (MFSubtractMask)- (voID)setSubtractMaskVIEw:(UIVIEw *)vIEw;- (UIVIEw *)subtractMaskVIEw;@end

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

vIEw.subtractMaskVIEw = maskVIEw;

四、局限性

1. subtractMaskVIEw 不会自动刷新

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

2. setSubtractMaskVIEw: 不宜被频繁调用

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

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

五、源码

请到 GitHub上查看完整代码。

总结

以上所述是小编给大家介绍的iOS中一行代码实现 UIVIEw 镂空效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

@H_404_242@ 总结

以上是内存溢出为你收集整理的iOS中一行代码实现 UIView 镂空效果全部内容,希望文章能够帮你解决iOS中一行代码实现 UIView 镂空效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1110027.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存