麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 系統(tǒng) > iOS > 正文

iOS中一行代碼實(shí)現(xiàn) UIView 鏤空效果

2019-10-21 18:39:16
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

iOS,代碼,UIView,鏤空

這是一種實(shí)現(xiàn) UIView 鏤空效果的方案,可以快速實(shí)現(xiàn)任意形狀的鏤空、文字的鏤空、帶鏤空的毛玻璃效果等。本質(zhì)上是 UIView 的 maskView 效果。

前言

首先來(lái)復(fù)習(xí)一下遮罩效果的實(shí)現(xiàn)。如果我們有一張圖片,又恰好有一個(gè)圓,當(dāng)我們把圓設(shè)置為圖片的遮罩時(shí),會(huì)得到這樣的結(jié)果。

iOS,代碼,UIView,鏤空

代碼實(shí)現(xiàn)看上去像是這樣:

view.maskView = maskView;

那么問(wèn)題來(lái)了,如果我們希望得到下面的結(jié)果,該怎么做呢?這看起來(lái)像是圖層的相減,即原來(lái)的圖層減去遮罩的部分。

iOS,代碼,UIView,鏤空

可惜蘋(píng)果爸爸不夠貼心,沒(méi)有提供方便的接口調(diào)用。讓我們來(lái)看看可以怎么實(shí)現(xiàn)。

一、思路

我們的最終目標(biāo)是,封裝出一個(gè)接口,調(diào)用方式類(lèi)似于 maskView 屬性,可以很方便地對(duì)一個(gè) UIView 做鏤空效果。

注:以下用 originView 指代需要上效果的 view ,用 maskView 指代充當(dāng)遮罩的 view 。

目前看來(lái),可以從兩個(gè)方向入手:

  1. 修改遮罩的繪制過(guò)程
  2. 修改 maskView 本身

方式一是指,在設(shè)置這個(gè)屬性的時(shí)候,對(duì) originView 的視圖進(jìn)行重新繪制,然后在繪制的時(shí)候,減掉 maskView的區(qū)域。

方式二是指,當(dāng)拿到 maskView 的時(shí)候,先對(duì) maskView 本身先進(jìn)行處理,將遮罩范圍取反。然后再做遮罩效果,由于遮罩的區(qū)域已經(jīng)相反,于是得到的結(jié)果也是相反的,就達(dá)到鏤空的目的。

看上去方式二比較靠譜,而且最后是調(diào)用 UIView 的 setMaskView: 來(lái)實(shí)現(xiàn),還可以保留原來(lái)遮罩的一些特性。比如當(dāng)修改 maskView 的 frame 的時(shí)候, originView 的遮罩位置也會(huì)相應(yīng)改變。

二、實(shí)現(xiàn)

生成相反的遮罩圖可以分為三步。假設(shè)一開(kāi)始拿到的 maskView 是下面這樣,讓我們來(lái)看下,轉(zhuǎn)換過(guò)程中遮罩圖每一步的變化。

iOS,代碼,UIView,鏤空

注:為了更直觀的效果,圖片中透明的部分用灰白相間格子來(lái)表示(以下相同)。

1、將 maskView 轉(zhuǎn)化為 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 對(duì)應(yīng)的 image 圖像。此時(shí)遮罩圖的大小會(huì)被同步為 originView 的大小。

iOS,代碼,UIView,鏤空 2、將

UIImage 轉(zhuǎn)換為只有 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);

這時(shí)候的 alphaOnlyContext 對(duì)應(yīng)的圖像是下面這樣,只保留了 alpha 通道。

iOS,代碼,UIView,鏤空 3、將

CGContextRef 中的 alpha 值進(jìn)行遍歷轉(zhuǎn)換

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];

轉(zhuǎn)換后,獲得的 result 圖像是:

iOS,代碼,UIView,鏤空

于是,我們就可以用 result 愉快地進(jìn)行 mask 了。

三、使用

我們可以將上述的步驟,封裝為一個(gè)方法,用 category 來(lái)實(shí)現(xiàn)。

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

這樣調(diào)用起來(lái)就十分方便了,一行代碼搞定:

view.subtractMaskView = maskView;

四、局限性

1. subtractMaskView 不會(huì)自動(dòng)刷新

我們知道,當(dāng) UIView 的 maskView 的內(nèi)容動(dòng)態(tài)修改時(shí),會(huì)實(shí)時(shí)反映到 UIView 中。但在本項(xiàng)目中, subtractMaskView 屬性會(huì)生成一張全新的圖片來(lái)作為遮罩圖,因?yàn)椴粫?huì)根據(jù) subtractMaskView 的內(nèi)容實(shí)時(shí)來(lái)刷新視圖。如果需要更新,必須手動(dòng)調(diào)用 setSubtractMaskView: 方法來(lái)重新生成遮罩圖。

2. setSubtractMaskView: 不宜被頻繁調(diào)用

setSubtractMaskView: 本質(zhì)上是生成一個(gè)新的遮罩圖的過(guò)程,該過(guò)程涉及圖片像素的遍歷轉(zhuǎn)換,較為耗時(shí),不宜頻繁調(diào)用。

綜上所述,這種方案適合只生成一次遮罩圖的場(chǎng)景。

 五、源碼

請(qǐng)到 GitHub 上查看完整代碼。

總結(jié)

以上所述是小編給大家介紹的iOS中一行代碼實(shí)現(xiàn) UIView 鏤空效果,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)VEVB武林網(wǎng)網(wǎng)站的支持!


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到IOS開(kāi)發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 欧洲成人综合网 | 18欧美性xxxx极品hd | 国产中出在线观看 | 男女亲热网站 | 黄色免费高清网站 | 免费黄色小网站 | 特黄一级小说 | 蜜桃网站免费 | 噜噜噜影院 | 亚洲精品久久久久久 | 在线2区 | 欧美日韩视频网站 | 中文国产在线视频 | 毛片大全免费看 | 国产1区2| 国产乱乱视频 | 欧美日韩一区,二区,三区,久久精品 | 久久亚洲综合色 | 27xxoo无遮挡动态视频 | 免费啪视频在线观看 | 久色视频网站 | 日韩精品中文字幕一区二区三区 | 成人视屏在线观看 | 成人在线观看一区二区三区 | 亚洲码无人客一区二区三区 | av在线影片 | 久久久久久久久久久国产精品 | 国产精品午夜在线观看 | 高清国产在线 | 欧美一级特黄aaaaaaa什 | 国产精品久久久久无码av | 国产精品白嫩白嫩大学美女 | 久久精品日本一区 | 在线免费观看日韩视频 | 久久91久久久久麻豆精品 | 狠狠99 | 国产一区二区视频网站 | 色人久久| 午夜视频国产 | 日本成人高清视频 | 天天看天天摸天天操 |