iOS 快速添加新功能提示

iOS快速添加新功能提示

当App迭代版本,增加新功能时,往往会在用户点进相应界面的时候,高亮显示新功能,并配上相应的图片文字吸引用户注意。例如XX功能更新了,办理什么业务再也不用排队了;通过XX新功能可以直接查询什么功能了…,如图简易提示:

screenshot
screenshot
screenshot
screenshot
screenshot

NOTE: 上图提示简易,实际需求由UI设计漂亮醒目的图片文字(点击上面的小图片可查看高清大图)。

方法思考

通常比较的做法,是由UI做出全屏的新功能提示图片,由开发人员控制进入相应界面时,全屏展示相应提示图片。

这样做的缺点主要有2个:

  1. 我们全屏添加到视图上面的图片,由于手机屏幕缩放的原因,提前设计的固定图片,上面高亮指向→的部分,往往和我们实际待高亮提示控件的位置不一致,图片移除时,会给人控件位置跳动一下的感觉;
  2. 全屏图片想要高清展示,压缩后也有上百KB,如果新功能提示较多,App安装包体积会明显增大。

通过观察发现,新功能提示大同小异,都是高亮待提示的部分,再用小的图片文字指向新功能提示用户。每个界面除了指向新功能的小图片提示,和后面蒙版高亮控件的位置不一样外,其他都一样。因此,我们可以通过代码生成高亮控件的背景图片,再叠加指向新功能的小图片即可,这样高亮提示的位置准确,图片体积也显著减少。

代码生成高亮待提示控件位置的背景图片


#pragma mark - 背景图片
//传入待提示控件的Frame 和切圆角的半径(默认为5)
-(UIImage *)imageWithTipRect:(CGRect)tipRect tipRectRadius:(CGFloat)tipRectRadius{
    
    //开启当前的图形上下文
    UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, 0.0);
    
    // 获取图形上下文,画板
    CGContextRef cxtRef = UIGraphicsGetCurrentContext();
    
    //将提示框增大,并与控件保持中心对齐,默认增大尺寸为切圆角的半径,需要特殊处理改下面尺寸
    CGFloat plusSize = tipRectRadius;
    CGRect tipRectPlus = CGRectMake(tipRect.origin.x - plusSize * 0.5, tipRect.origin.y - plusSize * 0.5, tipRect.size.width + plusSize, tipRect.size.height + plusSize);
    
    //绘制提示路径
    UIBezierPath *tipRectPath = [UIBezierPath bezierPathWithRoundedRect:tipRectPlus cornerRadius:tipRectRadius];
    
    //绘制蒙版
    UIBezierPath *screenPath = [UIBezierPath bezierPathWithRect:[UIScreen mainScreen].bounds];
    
    //填充色,默认为半透明,灰黑色背景;如果设置了自定义颜色,则使用自定义颜色
    if (self.bgColor) {
        CGContextSetFillColorWithColor(cxtRef, self.bgColor.CGColor);
    }else{
        CGContextSetFillColorWithColor(cxtRef, [UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.2].CGColor);
    }
    
    //添加路径到图形上下文
    CGContextAddPath(cxtRef, tipRectPath.CGPath);
    CGContextAddPath(cxtRef, screenPath.CGPath);
    
    //渲染,选择奇偶模式
    CGContextDrawPath(cxtRef, kCGPathEOFill);
    
    //从画布总读取图形
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    //关闭图形上下文
    UIGraphicsEndImageContext();
    
    return image;
}

添加指向新功能的提示图片

//背景容器
UIView *bView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
instance.bgView = bView;

//添加展示背景图片的图层
UIImageView *maskImageView = [[UIImageView alloc]initWithFrame:[UIScreen mainScreen].bounds];
[bView addSubview:maskImageView];

//添加指向新功能的提示图片
UIImageView *tipImageView = [[UIImageView alloc]initWithFrame:CGRectZero];
[bView addSubview:tipImageView];

//添加至Windows,展示在最上面
[[UIApplication sharedApplication].delegate.window addSubview: bView];
        

NOTE: 以上代码主要提供一个思路,您可能有更好的方法,欢迎指导。

封装

程序猿都是“很懒”的,这个“懒”是指不愿意干重复的工作。我们可以将此功能封装一下,最好下次使用时,一两行代码搞定。

封装思路分析:

  1. 从外部接口考虑,我们肯定需要传入多个待高亮提示的控件位置,由于CGRect不是对象,存入取出数组都需转换,我们直接把待提示的控件放入数组中,传入即可。
  2. 每个功能提示界面,肯定有一张指向新功能的图片,我们命名图片的时候,可以按照功能命名,例如functionImage0,functionImage1,functionImage2…;这样我们只需要传入一个图片名称前缀即可。
  3. 用户可能需要自定义背景色,需暴露一个设置颜色的属性。
  4. 指向新功能的图片位置默认在下方,可以自定义位置。
  5. 用户设置颜色和位置的顺序可能不固定,可能会先创建背景视图和添加功能提示图片。
  6. 提示图片的位置,肯定都是围绕在新功能高亮提示附近的,可用枚举列举常用位置。

API 接口

//定义为单例
+(instancetype)shareGuide;

/**
创建遮罩提示层
@param beGuidedViews 数组存入需要高亮的控件
@param prefixName 提示图片的前缀,例如preName0前缀为preName,图片按照此格式命名
*/
-(void)addGuideViews:(NSArray *)beGuidedViews imagePrefixName:(NSString *)prefixName;
        

完整代码

完整代码已经封装并上传至GitHub,下载地址GuideMaskDemo,如有错误,欢迎指正。

封装好的代码已上传至CocoaPods,名称为GuideMask ,可通过编辑Podfile文件,增加行 pod 'GuideMask',一键导入集成。

用法

GuideMask默认为单例,灰黑色半透明背景,提示图片展示在待提示功能下方。

假设提示图片依次命名为arrow0,arrow1,arrow2,arrow3…

#import "GuideMask.h"
//创建提示
GuideMask *mask = [GuideMask shareGuide];
//将待提示的View和提示小图片名称导入
[mask addGuideViews:@[self.richTextBtn,self.dateBtn,self.refreshBtn,self.fmdbBtn] imagePrefixName:@"arrow"];

当然你可以自定义背景颜色和透明度,和每张图片的位置,位置分为上,下,左,右,左上,左下,右上,右下,中心对齐,图片全屏覆盖手机等几种,能满足大部分需求。

//-------------------------可选----------------
//指定位置,默认在正下方
mask.tipImageLocation = @[@(GuideMaskPositionUp),@(GuideMaskPositionDown),@(GuideMaskPositionLeft),@(GuideMaskPositionRight),@(GuideMaskPositionLeftUp),@(GuideMaskPositionRightUp),@(GuideMaskPositionLeftDown),@(GuideMaskPositionRightDown)];
//背景色
mask.bgColor = [UIColor colorWithRed:128.0/255.0 green:128.0/255.0 blue:128.0/255.0 alpha:0.7];

如果您觉得有所帮助,请在GitHub GuideMaskDemo上赏个Star ⭐️,您的鼓励是我前进的动力!