美文网首页iOS 细节大集合程序员日记
iOS 引导页 --LaunchIntroduction

iOS 引导页 --LaunchIntroduction

作者: 9d8c8692519b | 来源:发表于2017-09-13 11:31 被阅读68次

一、前言

引导页,一个酷炫的页面,基本上每个应用程序刚安装后启动的时候都会有一个引导页,用于引导用户使用APP,怎么实现呢,首先来把引导页写好,说白了,它就是一个滚动视图,UIPageControl,按钮或者手势(进入主界面),这里我用的是手势点击进入主界面,(当然也你可以添加按钮),而且已经支持版本更新后显示新的引导页,先看效果:

引导页效果.gif

二、实现

特点
1、使用简单,一句代码搞定;
2、支持UIPageControl自定义,和是否需要UIPageControl;
3、在滚动视图的最后一个页面带有进入按钮和不带按钮,直接滚动就可隐藏引导页的选择,可根据需要定制;
4、支持自定义指示器的颜色;
5、支持应用升级后显示新的引导页。

实现原理

创建一个UIView对象view,然后在view上添加一个scrollview,scrollview上添加需要的图片及按钮等,然后程序第一次启动或者应用升级后把view添加到当前的window上,这样view就显示了出来,当滑动到最后或者点击进入程序的按钮时将view从window上移除,为了更好的体验效果,在view移除时加了一个0.5s的动画,产生了一个view渐渐消失的效果。

源码实现

头文件

#import <UIKit/UIKit.h>

#define LScreen_height  [[UIScreen mainScreen] bounds].size.height
#define LScreen_width   [[UIScreen mainScreen] bounds].size.width

@interface LaunchIntroductionView : UIView

/**
 *  选中page的指示器颜色,默认白色
 */
@property (nonatomic, strong) UIColor *currentColor;

/**
 *  其他状态下的指示器的颜色,默认
 */
@property (nonatomic, strong) UIColor *nomalColor;

/**
 *  不带按钮的引导页,滑动到最后一页,再向右滑直接隐藏引导页
 *
 *  @param imageNames 背景图片数组
 *
 *  @return   LaunchIntroductionView对象
 */
+(instancetype)sharedWithImages:(NSArray *) imageNames isNeedPageControl:(BOOL )needPageControl;

/**
 *  带按钮的引导页
 *
 *  @param imageNames      背景图片数组
 *  @param buttonImageName 按钮的图片
 *  @param frame           按钮的frame
 *
 *  @return LaunchIntroductionView对象
 */
+(instancetype)sharedWithImages:(NSArray *) imageNames isNeedPageControl:(BOOL )needPageControl buttonImage:(NSString *) buttonImageName buttonFrame:(CGRect ) frame;

/**
 用storyboard创建的project调用此方法
 
 @param storyboardName storyboardName
 @param imageNames 图片名字数组
 @return LaunchIntroductionView对象
 */
+ (instancetype)sharedWithStoryboardName:(NSString *)storyboardName images:(NSArray *)imageNames isNeedPageControl:(BOOL )needPageControl;

/**
 用storyboard创建的project调用此方法
 
 @param storyboardName storyboardName
 @param imageNames 图片名字数组
 @param buttonImageName 按钮图片名字
 @param frame 按钮的frame
 @return LaunchIntroductionView对象
 */
+(instancetype)sharedWithStoryboard:(NSString *)storyboardName images:(NSArray *) imageNames isNeedPageControl:(BOOL )needPageControl buttonImage:(NSString *) buttonImageName buttonFrame:(CGRect ) frame;

@end

import "LaunchIntroductionView.h" 方法实现

#import "LaunchIntroductionView.h"

static NSString *const kAppVersion = @"appVersion";
@interface LaunchIntroductionView ()<UIScrollViewDelegate>
{
    UIScrollView  *launchScrollView;
    UIPageControl *page;
}

@end

@implementation LaunchIntroductionView

NSArray *images;
BOOL isScrollOut;//在最后一页再次滑动是否隐藏引导页
BOOL showPageControl; // 是否显示展示PageControl
CGRect enterBtnFrame;
NSString *enterBtnImage;
static LaunchIntroductionView *launch = nil;
NSString *storyboard;

#pragma mark - 创建对象-->>不带button
+(instancetype)sharedWithImages:(NSArray *) imageNames isNeedPageControl:(BOOL )needPageControl{
    showPageControl = needPageControl;
    images = imageNames;
    isScrollOut = YES;
    launch = [[LaunchIntroductionView alloc] initWithFrame:CGRectMake(0, 0, LScreen_width, LScreen_height)];
    launch.backgroundColor = [UIColor whiteColor];
    return launch;
}
#pragma mark - 创建对象-->>带button
+(instancetype)sharedWithImages:(NSArray *)imageNames isNeedPageControl:(BOOL )needPageControl buttonImage:(NSString *)buttonImageName buttonFrame:(CGRect)frame{
    showPageControl = needPageControl;
    images = imageNames;
    isScrollOut = NO;
    enterBtnFrame = frame;
    enterBtnImage = buttonImageName;
    launch = [[LaunchIntroductionView alloc] initWithFrame:CGRectMake(0, 0, LScreen_width, LScreen_height)];
    launch.backgroundColor = [UIColor whiteColor];
    return launch;
}
#pragma mark - 用storyboard创建的项目时调用,不带button
+ (instancetype)sharedWithStoryboardName:(NSString *)storyboardName images:(NSArray *)imageNames isNeedPageControl:(BOOL )needPageControl {
    showPageControl = needPageControl;
    images = imageNames;
    storyboard = storyboardName;
    isScrollOut = YES;
    launch = [[LaunchIntroductionView alloc] initWithFrame:CGRectMake(0, 0, LScreen_width, LScreen_height)];
    launch.backgroundColor = [UIColor whiteColor];
    return launch;
}
#pragma mark - 用storyboard创建的项目时调用,带button
+ (instancetype)sharedWithStoryboard:(NSString *)storyboardName images:(NSArray *)imageNames isNeedPageControl:(BOOL )needPageControl buttonImage:(NSString *)buttonImageName buttonFrame:(CGRect)frame{
    showPageControl = needPageControl;
    images = imageNames;
    isScrollOut = NO;
    enterBtnFrame = frame;
    storyboard = storyboardName;
    enterBtnImage = buttonImageName;
    launch = [[LaunchIntroductionView alloc] initWithFrame:CGRectMake(0, 0, LScreen_width, LScreen_height)];
    launch.backgroundColor = [UIColor whiteColor];
    return launch;
}
#pragma mark - 初始化
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        if ([self isFirstLauch]) {
            UIStoryboard *story;
            if (storyboard) {
                story = [UIStoryboard storyboardWithName:storyboard bundle:nil];
            }
            UIWindow *window = [UIApplication sharedApplication].windows.lastObject;
            if (story) {
                UIViewController * vc = story.instantiateInitialViewController;
                window.rootViewController = vc;
                [vc.view addSubview:self];
            }else {
                [window addSubview:self];
            }
            [self addImages];
        }else{
            [self removeFromSuperview];
        }
    }
    return self;
}
#pragma mark - 判断是不是首次登录或者版本更新
-(BOOL )isFirstLauch{
    //获取当前版本号
    NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary];
    NSString *currentAppVersion = infoDic[@"CFBundleShortVersionString"];
    //获取上次启动应用保存的appVersion
    NSString *version = [[NSUserDefaults standardUserDefaults] objectForKey:kAppVersion];
    //版本升级或首次登录
    if (version == nil || ![version isEqualToString:currentAppVersion]) {
        [[NSUserDefaults standardUserDefaults] setObject:currentAppVersion forKey:kAppVersion];
        [[NSUserDefaults standardUserDefaults] synchronize];
        return YES;
    }else{
        return NO;
    }
}
#pragma mark - 添加引导页图片
-(void)addImages{
    [self createScrollView];
}
#pragma mark - 创建滚动视图
-(void)createScrollView{
    launchScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, LScreen_width, LScreen_height)];
    launchScrollView.showsHorizontalScrollIndicator = NO;
    launchScrollView.bounces = NO;
    launchScrollView.pagingEnabled = YES;
    launchScrollView.delegate = self;
    launchScrollView.contentSize = CGSizeMake(LScreen_width * images.count, LScreen_height);
    [self addSubview:launchScrollView];
    
    // GCD的快速迭代方法
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 2); //优先级 设高点吧!
    dispatch_apply(images.count, queue, ^(size_t index) {
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(index * LScreen_width, 0, LScreen_width, LScreen_height)];
        imageView.image = [UIImage imageNamed:images[index]];
        //判断要不要添加消失事件
        if (index == images.count - 1 && isScrollOut) {
            NSLog(@"添加消失事件enterBtnClick");
            imageView.userInteractionEnabled = YES;
            [imageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapEnterClick)]];
        }
        [launchScrollView addSubview:imageView];
    });
    
    if (showPageControl) {
        page = [[UIPageControl alloc] initWithFrame:CGRectMake(0, LScreen_height - 50, LScreen_width, 30)];
        page.numberOfPages = images.count;
        page.backgroundColor = [UIColor clearColor];
        page.currentPage = 0;
        page.defersCurrentPageDisplay = YES;
        [self addSubview:page];
        
        [self addObserver:self forKeyPath:@"currentColor" options:NSKeyValueObservingOptionNew context:nil];
        [self addObserver:self forKeyPath:@"nomalColor" options:NSKeyValueObservingOptionNew context:nil];
        
        // 可在这里面 设置 颜色
//        self.currentColor = [UIColor redColor];
    }
}
#pragma mark - 进入
-(void)tapEnterClick{
    NSLog(@"Tap消失事件hideGuidView");
    [self hideGuidView];
}
#pragma mark - 隐藏引导页
-(void)hideGuidView{
    [UIView animateWithDuration:0.5 animations:^{
        self.alpha = 0;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self removeFromSuperview];
        });
        
    }];
}
#pragma mark - scrollView Delegate
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    int cuttentIndex = (int)(scrollView.contentOffset.x + LScreen_width/2)/LScreen_width;
    if (cuttentIndex == images.count - 1) {
        if ([self isScrolltoLeft:scrollView]) {
            if (!isScrollOut) {
                return ;
            }
            [self hideGuidView];
        }
    }
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    if (scrollView == launchScrollView) {
        int cuttentIndex = (int)(scrollView.contentOffset.x + LScreen_width/2)/LScreen_width;
        page.currentPage = cuttentIndex;
    }
}
#pragma mark - 判断滚动方向
-(BOOL )isScrolltoLeft:(UIScrollView *) scrollView{
    //返回YES为向左反动,NO为右滚动
    if ([scrollView.panGestureRecognizer translationInView:scrollView.superview].x < 0) {
        return YES;
    }else{
        return NO;
    }
}
#pragma mark - KVO监测值的变化
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
    if ([keyPath isEqualToString:@"currentColor"]) {
        page.currentPageIndicatorTintColor = self.currentColor;
    }
    if ([keyPath isEqualToString:@"nomalColor"]) {
        page.pageIndicatorTintColor = self.nomalColor;
    }
}

传的参数稍微多了点,都是可以根据需要来定制。这里需要说明背景图片数组暂时只考虑本地Image。

总结

引导页目前大多APP都需要,只是一个简单的新特性展示。所以在开发过程中能简单处理尽量简洁处理。所以本人通过查阅资料。综合了一个比较简洁的处理方式,能够满足目前对于引导页的大多普通样式。支持使用storyboard时创建和普通创建的模式!👇是Demo源码地址

Demo下载地址 前往GitHub

相关文章

  • iOS 引导页 --LaunchIntroduction

    一、前言 引导页,一个酷炫的页面,基本上每个应用程序刚安装后启动的时候都会有一个引导页,用于引导用户使用APP,怎...

  • ios引导页

    首先修改 App Transport Security SettingsAllow Arbitrary Loads...

  • iOS 引导页

    在AppDelegate.m中:我们需要两个Viewcongtroller来实现;myViewController...

  • ios 引导页

    目标功能 能够快速实现普通引导页功能. 提供自定义view的加载模式. 提供特定样式的加载模式,只需要配置即可. ...

  • iOS引导页

    在我们项目中经常会用到引导页,引导页主要功能就是向用户展示你的产品。 这是我写的一个例子的效果图(图片是随便找的):

  • iOS引导页

    引导页是App中的基本功能,指导用户理解某些操作或版本变化等等。 引导页可能出现在任何时候,页面内容会根据可交互度...

  • iOS引导页、启动页

    前言 这里使用 launchScreen 、.storyboard 文件创建启动图和引导页。首次打开项目或者更新后...

  • iOS 引导页适配

    1,图片适配,最早以前是自己命名规范,例如@1x,@2x,@3x等,3套图基本上就够用了 2,在iPhone X之...

  • ios开发,引导页

    在viewController.m里面 @interface ViewController () { UISc...

  • ios 引导页 新闻

    首先修改 App Transport Security Settings Allow Arbitrary Load...

网友评论

    本文标题:iOS 引导页 --LaunchIntroduction

    本文链接:https://www.haomeiwen.com/subject/jpycsxtx.html