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

二、实现
特点
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