iOS 半透明新手引導(dǎo)的封裝

Liu

經(jīng)過(guò)一個(gè)月的加班加點(diǎn),由我負(fù)責(zé)的公司分項(xiàng)目終于完成了階段性的開(kāi)發(fā),在改bug的空余,總結(jié)了一下工程中用到的一些東西,現(xiàn)把我封裝的“半透明新手引導(dǎo)功能”分享出來(lái),供大家交流學(xué)習(xí),有不足,還望提出,共同進(jìn)步~

1.功能圖

一般的新手引導(dǎo)頁(yè),只需要出現(xiàn)一次,一次顯示出全部需要提示的功能就可以了,像這樣:

MJGuide0.png

但在我們項(xiàng)目中,不僅僅這樣,還要通過(guò)點(diǎn)擊一次次的顯示不同的功能提示,一次可以顯示一張,也可以顯示多張,像這樣:

MJGuide1.gif
MJGuide2.gif
2.代碼區(qū)

萬(wàn)變不離其宗,如果你的項(xiàng)目只需要簡(jiǎn)單的一個(gè)新功能引導(dǎo),并不需要那么多引導(dǎo)視圖,那么我們可以用以下代碼來(lái)實(shí)現(xiàn),我也是根據(jù)此代碼來(lái)封裝多視圖的,參考 黑黑的小土豆

  1. 創(chuàng)建半透明視圖加載在window上,并添加點(diǎn)擊手勢(shì)
CGRect frame = [UIScreen mainScreen].bounds;
UIView * bgView = [[UIView alloc]initWithFrame:frame];
bgView.backgroundColor = RGBHEXA(0x323232, 0.8);

UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(sureTapClick:)];
[bgView addGestureRecognizer:tap];
[[UIApplication sharedApplication].keyWindow addSubview:bgView];
  1. 獲取目標(biāo)視圖在window坐標(biāo)系的frame
CGRect rect = [self.view convertRect:self.wobBtn.frame toView:[UIApplication sharedApplication].keyWindow];
  1. UIBezierPath 繪制鏤空路徑
UIBezierPath *path = [UIBezierPath bezierPathWithRect:frame];
[path appendPath:[[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:5] bezierPathByReversingPath]];
// bezierPathByReversingPath 的意思就是反轉(zhuǎn) 就是將你設(shè)置的路徑以外的部分加入到路徑中這樣 你設(shè)置的路徑就不在繪制的范圍之內(nèi)。在setMaskLayer的時(shí)候 你設(shè)置的那部分路徑就沒(méi)有了 就成了鏤空的。 clockwise 這個(gè)值得意思也是這樣。
  1. 渲染路徑
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = path.CGPath;
shapeLayer.strokeColor = [UIColor blueColor].CGColor;
[bgView.layer setMask:shapeLayer];
  1. 把UI設(shè)計(jì)的功能引導(dǎo)圖加到半透明視圖上
UIImageView * imageView = [[UIImageView alloc]initWithFrame:CGRectMake(frame.size.width -225,CGRectGetMaxY(rect),200, 100)];
imageView.image = [UIImage imageNamed:@"img_guidehelp_bookshelf_purchasehistory"];
[bgView addSubview:imageView];
  1. 手勢(shì)事件
- (void)sureTapClick:(UITapGestureRecognizer *)tap{
    UIView * view = tap.view;
    [view removeFromSuperview];
    [view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    [view removeGestureRecognizer:tap];
}
3.封裝區(qū)

MXRGuideMaskView 想要展示多個(gè)新功能引導(dǎo)視圖,肯定需要接受外界傳遞參數(shù):圖片組、圖片位置組、鏤空區(qū)位置組、展示順序

/**
 初始化數(shù)據(jù)
 
 @param images 圖片字符串
 @param imageframeArr 圖片位置 @[[NSValue valueWithCGRect:CGRectMake(20, 205, 170, 50)]]
 @param rectArr 矩形透明區(qū)位置
 @param orderArr 順序 例:@[@2,@1,@3]
 */
- (void)addImages:(NSArray *)images imageFrame:(NSArray *)imageframeArr TransparentRect:(NSArray *)rectArr orderArr:(NSArray *)orderArr;

然后,在 .m 方法中,判斷具體的邏輯:

  1. 判斷順序數(shù)組總數(shù)是否等于圖片數(shù)組,避免不必要的 crash
NSInteger numCount = 0;
for (NSNumber * num in orderArr) {
    NSInteger order = [num integerValue];
    numCount += order;
}
if (numCount != images.count) {
    return;
}
  1. 準(zhǔn)備數(shù)據(jù)
self.orderArr = [orderArr mutableCopy];
[images enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) {
    UIImage * image = [UIImage imageNamed:obj];
    [self.imageArr addObject:image];
}];
self.frameArr = [imageframeArr mutableCopy];

for (NSInteger i=0; i<rectArr.count; i++) {
    UIBezierPath *transparentPath = [UIBezierPath bezierPathWithRoundedRect:[rectArr[i] CGRectValue] cornerRadius:5];
    [self.transparentPaths addObject:transparentPath];
}
  1. 控制多個(gè)顯示邏輯
for (NSInteger i=0; i<[orderArr[0] integerValue]; i++) {
    [self addImage:_imageArr[i] withFrame:[_frameArr[i] CGRectValue]];
    [self addTransparentPath:_transparentPaths[i]];
}
- (void)addImage:(UIImage*)image withFrame:(CGRect)frame{
    
    UIImageView * imageView   = [[UIImageView alloc]initWithFrame:frame];
    imageView.backgroundColor = [UIColor clearColor];
    imageView.image           = image;
    [self addSubview:imageView];
}

- (void)addTransparentPath:(UIBezierPath *)transparentPath {
    [self.overlayPath appendPath:transparentPath];
    self.fillLayer.path = self.overlayPath.CGPath;
}

4.點(diǎn)擊事件

- (void)tapClickedMaskView{
    
    _index++;
    if (_index < _orderArr.count) {
        
        [self refreshMask];
        [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
        
        // 控制多個(gè)顯示邏輯
        NSInteger baseNum = [_orderArr[_index-1] integerValue];
        countNum = countNum + baseNum;
        NSInteger endNum = [_orderArr[_index] integerValue]+countNum;
        for (NSInteger i=countNum; i<endNum; i++) {
            
            [self addTransparentPath:_transparentPaths[i]];
            [self addImage:_imageArr[i] withFrame:[_frameArr[i] CGRectValue]];
        }
    }else{
        countNum = 0;
        [self dismissMaskView];
    }
}
- (void)refreshMask {
    
    UIBezierPath *overlayPath = [self generateOverlayPath];
    self.overlayPath = overlayPath;
    
}

- (UIBezierPath *)generateOverlayPath {
    
    UIBezierPath *overlayPath = [UIBezierPath bezierPathWithRect:self.bounds];
    [overlayPath setUsesEvenOddFillRule:YES];
    
    return overlayPath;
}

4.使用方法

使用起來(lái)也很方便,只需要初始化MXRGuideMaskView視圖,然后傳遞參數(shù),展示出來(lái),就OK啦~

- (void)setupGuideView{
    MXRGuideMaskView *maskView = [MXRGuideMaskView new];
    [maskView addImages:imageArr imageFrame:imgFrameArr TransparentRect:transparentRectArr orderArr:orderArr];
    [maskView showMaskViewInView:self.view];
}

是不是很簡(jiǎn)單那,嚶嚶嚶 ~
整理了一個(gè)【Demo】出來(lái),喜歡就點(diǎn)贊哦 ~

star.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明AI閱讀 16,236評(píng)論 3 119
  • 這片羽毛來(lái)自白鵝身上,它已經(jīng)飄蕩了很長(zhǎng)時(shí)間了,它飄過(guò)村莊,在一扎金黃的麥垛上靜靜的休息了一段時(shí)間,一個(gè)孩子將他拾起...
    春遲秋暮閱讀 529評(píng)論 0 2
  • 這片園子, 往左走,是泰坦尼克, 往右走,是新鴛鴦蝴蝶夢(mèng), 都是中國(guó)拳。 中間最好, 我知道那兒周末有京劇。 這會(huì)...
    愛(ài)穩(wěn)閱讀 354評(píng)論 0 0
  • 結(jié)構(gòu)體定義 結(jié)構(gòu)體,通俗講就像是打包封裝,把一些有共同特征(比如同屬于某一類事物的屬性,往往是某種業(yè)務(wù)相關(guān)屬性的聚...
    巧克力er閱讀 343評(píng)論 1 1

友情鏈接更多精彩內(nèi)容