iOS 半透明新手引导 手把手教你做

一、效果展示

这里写图片描述
这里写图片描述

这种类型的新手引导比较常见,用于告诉用户某个按钮的作用,或者提醒用户可以进行某种交互操作。引导样式是在界面上加了一个半透明的引导图,高亮部分就是要突出的区域

二、怎么做?

方案有很多种,不同的方案有不同的优缺点,这里列举两种常见的方案

1. 方案一:生成整张引导图

(1). 导出引导图

让设计师导出各个尺寸的引导图,引导图只包含指引部分,不包括背景,导出的引导图样式如下:


这里写图片描述
这里写图片描述

需要导出iPhone4,iPhone5,iPhone6,iPhone6 plus 共4个尺寸,如果适配iPad,还需要导出iPad的

(2). 编码

因为整张图导出了,所以代码部分就简单了,不需要考虑布局问题,直接生成一个imageView放上去,然后给它添加个点击事件即可

代码如下:

- (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以上的系统才能够自动识别出来,如果要向前兼容,则图片名那里需要自行判断设备类型,然后指定对应的图片名称

(3). 优缺点

这种方案的优点是
a. 快速
只要设计师做好效果图以后,把蒙层导出成各种规格即可,90%的工作量都在设计师身上,程序员只需要简单地添加视图和事件即可

b. 维护成本低
当界面发生变化,或者引导图需要调整时,只需要设计师重新生成图片,然后替换就可以了

但这种方案的缺点也很多:
a. 图片占据空间大
每种设备一张图片,图片还是全屏规格的,可能还要适配横屏,明显会增加app安装包的大小

b. 图片无法复用
一张引导图只能用于一个地方,其他地方不可能会用得上

2. 方案二:图片拼接

图片拼接的思路是这样的,通过若干张图片拼成一个遮罩层,然后再在上面放其他元素,如下图所示


这里写图片描述
这里写图片描述
(1). 准备图片

这里需要准备3张图片
a. 空心的椭圆遮罩层

这里写图片描述
这里写图片描述

中间是透明,周围是白色的,白色部分可以在遮罩过程中修改成任意的颜色

b. 小箭头

这里写图片描述
这里写图片描述

c. 确定按钮

这里写图片描述
这里写图片描述

(2). 编码

这里只介绍部分代码的编写过程

a. 接口
接口的定义:

  • (void)showInView:(UIView *)view maskBtn:(UIButton *)btn;
    view:引导图的父视图
    btn:被遮罩的按钮

接口的实现:

  • (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. 修改遮罩层
加载空心的椭圆图片后,先对白色区域进行处理,把它改成黑色半透明
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;
    }
    这里会将图片中白色的部分改成任意的颜色,我们要将空心的椭圆图片变成这样


    这里写图片描述
    这里写图片描述

c. 生成上下左右4个黑色半透明视图
分别放在空心椭圆图片的上、下、左、右四个方位

  • (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. 视图布局
这里有几个需要注意的地方:
c-1. 被拼接的视图的 x,y,width,height 的值需要取整,因为浮点数可能会导致衔接部位出现白边,尤其是在iPhone6 plus上,原因是手机的分辨率问题,所以这里最好使用整数

c-2. 在 layoutSubviews 函数中进行布局,这里布局的好处是横竖屏适配都能够平滑过渡,而且不需要手动更新

布局代码如下:

  • (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). 优缺点

优点:
a. 节约空间
一般就只需要几个小图,然后就可以组装成一张引导图了

b. 图片可重用
按钮、椭圆图、小箭头这一类的图片可能被其他引导图继续使用

缺点:
a. 编码时间较长
每一个界面元素都需要通过编码来实现,每一次改动也需要调整代码

三、总结

第一种方案比较适合小项目,主要是速度快,适合快速迭代
第二种方案适合长期更新的项目,节约app空间
Demo地址:
https://github.com/sunljz/demo/tree/master/GuideDemo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容