服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS中一行代码实现 UIView 镂空效果

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

2021-05-17 16:43雷曼同学 IOS

这篇文章主要介绍了一行代码实现 UIView 镂空效果,这是一种实现 UIView 镂空效果的方案,可以快速实现任意形状的镂空、文字的镂空、带镂空的毛玻璃效果等。需要的朋友可以参考下

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

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

前言

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

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

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

?
1
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

?
1
2
3
4
5
6
7
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 值进行遍历转换

?
1
2
3
4
5
6
7
8
9
10
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 来实现。

?
1
2
3
4
@interface uiview (mfsubtractmask)
- (void)setsubtractmaskview:(uiview *)view;
- (uiview *)subtractmaskview;
@end

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

?
1
view.subtractmaskview = maskview;

四、局限性

1. subtractmaskview 不会自动刷新

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

2. setsubtractmaskview: 不宜被频繁调用

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

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

 五、源码

请到 github 上查看完整代码。

总结

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

原文链接:https://www.jianshu.com/p/fb304a81bbda

延伸 · 阅读

精彩推荐
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01