iOS 半透明新手引導(dǎo) 手把手教你做

一、效果展示

這里寫圖片描述
這里寫圖片描述

這種類型的新手引導(dǎo)比較常見,用于告訴用戶某個(gè)按鈕的作用,或者提醒用戶可以進(jìn)行某種交互操作。引導(dǎo)樣式是在界面上加了一個(gè)半透明的引導(dǎo)圖,高亮部分就是要突出的區(qū)域

二、怎么做?

方案有很多種,不同的方案有不同的優(yōu)缺點(diǎn),這里列舉兩種常見的方案

1. 方案一:生成整張引導(dǎo)圖

(1). 導(dǎo)出引導(dǎo)圖

讓設(shè)計(jì)師導(dǎo)出各個(gè)尺寸的引導(dǎo)圖,引導(dǎo)圖只包含指引部分,不包括背景,導(dǎo)出的引導(dǎo)圖樣式如下:


這里寫圖片描述
這里寫圖片描述

需要導(dǎo)出iPhone4,iPhone5,iPhone6,iPhone6 plus 共4個(gè)尺寸,如果適配iPad,還需要導(dǎo)出iPad的

(2). 編碼

因?yàn)檎麖垐D導(dǎo)出了,所以代碼部分就簡(jiǎn)單了,不需要考慮布局問(wèn)題,直接生成一個(gè)imageView放上去,然后給它添加個(gè)點(diǎn)擊事件即可

代碼如下:

- (void)addGuideView {
    NSString *imageName = nil;
    if (DEVICE_IS_IPHONE5) {
        imageName = @"guide-568h";
    } else {
        imageName = @"guide";
    }
   
    UIImage *image = [UIImage imageNamed:imageName];
    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    imageView.frame = self.view.bounds;
    imageView.userInteractionEnabled = YES;
   
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissGuideView)];
    [imageView addGestureRecognizer:tap];
   
    [self.view addSubview:imageView];
}

這里需要特別注意:
@3x 的圖片需要iOS8以上的系統(tǒng)才能夠自動(dòng)識(shí)別出來(lái),如果要向前兼容,則圖片名那里需要自行判斷設(shè)備類型,然后指定對(duì)應(yīng)的圖片名稱

(3). 優(yōu)缺點(diǎn)

這種方案的優(yōu)點(diǎn)是
a. 快速
只要設(shè)計(jì)師做好效果圖以后,把蒙層導(dǎo)出成各種規(guī)格即可,90%的工作量都在設(shè)計(jì)師身上,程序員只需要簡(jiǎn)單地添加視圖和事件即可

b. 維護(hù)成本低
當(dāng)界面發(fā)生變化,或者引導(dǎo)圖需要調(diào)整時(shí),只需要設(shè)計(jì)師重新生成圖片,然后替換就可以了

但這種方案的缺點(diǎn)也很多:
a. 圖片占據(jù)空間大
每種設(shè)備一張圖片,圖片還是全屏規(guī)格的,可能還要適配橫屏,明顯會(huì)增加app安裝包的大小

b. 圖片無(wú)法復(fù)用
一張引導(dǎo)圖只能用于一個(gè)地方,其他地方不可能會(huì)用得上

2. 方案二:圖片拼接

圖片拼接的思路是這樣的,通過(guò)若干張圖片拼成一個(gè)遮罩層,然后再在上面放其他元素,如下圖所示


這里寫圖片描述
這里寫圖片描述
(1). 準(zhǔn)備圖片

這里需要準(zhǔn)備3張圖片
a. 空心的橢圓遮罩層

這里寫圖片描述
這里寫圖片描述

中間是透明,周圍是白色的,白色部分可以在遮罩過(guò)程中修改成任意的顏色

b. 小箭頭

這里寫圖片描述
這里寫圖片描述

c. 確定按鈕

這里寫圖片描述
這里寫圖片描述

(2). 編碼

這里只介紹部分代碼的編寫過(guò)程

a. 接口
接口的定義:

  • (void)showInView:(UIView *)view maskBtn:(UIButton *)btn;
    view:引導(dǎo)圖的父視圖
    btn:被遮罩的按鈕

接口的實(shí)現(xiàn):

  • (void)showInView:(UIView *)view maskBtn:(UIButton *)btn {
    self.parentView = view;
    self.maskBtn = btn;

    self.alpha = 0;
    [view addSubview:self];
    [UIView animateWithDuration:0.2 animations:^{
    self.alpha = 1;
    } completion:nil];
    }

b. 修改遮罩層
加載空心的橢圓圖片后,先對(duì)白色區(qū)域進(jìn)行處理,把它改成黑色半透明
UIImage *image = [UIImage imageNamed:@"whiteMask"];
image = [image maskImage:[[UIColor blackColor] colorWithAlphaComponent:0.71]];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

  • (UIImage *)maskImage:(UIColor *)maskColor
    {
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);

    UIGraphicsBeginImageContext(rect.size);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0, rect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextClipToMask(context, rect, self.CGImage);
    CGContextSetFillColorWithColor(context, maskColor.CGColor);
    CGContextFillRect(context, rect);

    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return smallImage;
    }
    這里會(huì)將圖片中白色的部分改成任意的顏色,我們要將空心的橢圓圖片變成這樣


    這里寫圖片描述
    這里寫圖片描述

c. 生成上下左右4個(gè)黑色半透明視圖
分別放在空心橢圓圖片的上、下、左、右四個(gè)方位

  • (UIView *)topMaskView {
    if (!_topMaskView) {
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.71];
    _topMaskView = view;
    }
    return _topMaskView;
    }

  • (UIView *)bottomMaskView {
    if (!_bottomMaskView) {
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.71];
    _bottomMaskView = view;
    }
    return _bottomMaskView;
    }

  • (UIView *)leftMaskView {
    if (!_leftMaskView) {
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.71];
    _leftMaskView = view;
    }
    return _leftMaskView;
    }

  • (UIView *)rightMaskView {
    if (!_rightMaskView) {
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.71];
    _rightMaskView = view;
    }
    return _rightMaskView;
    }

d. 視圖布局
這里有幾個(gè)需要注意的地方:
c-1. 被拼接的視圖的 x,y,width,height 的值需要取整,因?yàn)楦↑c(diǎn)數(shù)可能會(huì)導(dǎo)致銜接部位出現(xiàn)白邊,尤其是在iPhone6 plus上,原因是手機(jī)的分辨率問(wèn)題,所以這里最好使用整數(shù)

c-2. 在 layoutSubviews 函數(shù)中進(jìn)行布局,這里布局的好處是橫豎屏適配都能夠平滑過(guò)渡,而且不需要手動(dòng)更新

布局代碼如下:

  • (void)layoutSubviews {
    [super layoutSubviews];
    self.frame = _parentView.bounds;
    _maskBg.frame = self.bounds;
    _btnMaskView.center = [_maskBtn.superview convertPoint:_maskBtn.center toView:_maskBtn.superview];

    CGRect btnMaskRect = _btnMaskView.frame;
    btnMaskRect.size = CGSizeMake(floor(btnMaskRect.size.width), floor(btnMaskRect.size.height));
    btnMaskRect.origin = CGPointMake(floor(btnMaskRect.origin.x), floor(btnMaskRect.origin.y));
    _btnMaskView.frame = btnMaskRect;

    _topMaskView.left = 0;
    _topMaskView.top = 0;
    _topMaskView.height = _btnMaskView.top;
    _topMaskView.width = self.width;

    _bottomMaskView.left = 0;
    _bottomMaskView.top = _btnMaskView.bottom;
    _bottomMaskView.width = self.width;
    _bottomMaskView.height = self.height - _bottomMaskView.top;

    _leftMaskView.left = 0;
    _leftMaskView.top = _btnMaskView.top;
    _leftMaskView.width = _btnMaskView.left;
    _leftMaskView.height = _btnMaskView.height;

    _rightMaskView.left = _btnMaskView.right;
    _rightMaskView.top = _btnMaskView.top;
    _rightMaskView.width = self.width - _rightMaskView.left;
    _rightMaskView.height = _btnMaskView.height;

    _arrwoView.right = _btnMaskView.left + 24;
    _arrwoView.bottom = _btnMaskView.top - 8;
    _tipsLabel.right = _arrwoView.left - 6;
    _tipsLabel.bottom = _arrwoView.top + 10;

    _okBtn.centerX = self.width/2;
    _okBtn.bottom = _btnMaskView.top - 80;
    }

(3). 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):
a. 節(jié)約空間
一般就只需要幾個(gè)小圖,然后就可以組裝成一張引導(dǎo)圖了

b. 圖片可重用
按鈕、橢圓圖、小箭頭這一類的圖片可能被其他引導(dǎo)圖繼續(xù)使用

缺點(diǎn):
a. 編碼時(shí)間較長(zhǎng)
每一個(gè)界面元素都需要通過(guò)編碼來(lái)實(shí)現(xiàn),每一次改動(dòng)也需要調(diào)整代碼

三、總結(jié)

第一種方案比較適合小項(xiàng)目,主要是速度快,適合快速迭代
第二種方案適合長(zhǎng)期更新的項(xiàng)目,節(jié)約app空間
Demo地址:
https://github.com/sunljz/demo/tree/master/GuideDemo

最后編輯于
?著作權(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)容

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