1. 程式人生 > >IOS 一句代碼搞定啟動引導頁

IOS 一句代碼搞定啟動引導頁

caption tom pro strong ole 內容 exp def alt

  • 前言
    引導頁,一個酷炫的頁面,自從微博用了之後一下就火起來了,對於現在來說一個app如果沒有引導頁似乎總顯那麽不接地氣,那麽為了讓我們的app也“高大上”一次,我寫了一個demo來實現啟動引導頁的實現,鑒於我的強迫癥,使用起來也是盡可能的簡單才算罷休,這不,一句代碼就搞定了,而且支持版本更新後顯示新的引導頁,先看效果:
技術分享
LaunchIntroduction.gif


demo中封裝了兩個方法以供調用,一個是在滾動視圖的最後一個頁面帶有進入按鈕,一個是不帶按鈕,直接滾動就可隱藏引導頁。


  • 特點
    1、使用簡單,一句代碼搞定
    2、支持自定義指示器的顏色
    3、支持應用升級後顯示新的引導頁
  • 下載地址:LaunchIntroductionDemo 下載
    先說使用方法,來不及的童靴可以先嘗嘗鮮:

    1、導入LaunchIntroductionView.m 和 LaunchIntroductionView.h 文件到工程中
    2、在APPDelegate中包含頭文件 #import "LaunchIntroductionView.h"
    3、調用:
    [LaunchIntroductionView sharedWithImages:@[@"launch0.jpg",@"launch1.jpg",@"launch2.jpg",@"launch3"]];
    4、還有一種調用方法,是帶button的:

    [LaunchIntroductionView sharedWithImages:@[@"launch0.jpg",@"launch1.jpg",@"launch2.jpg",@"launch3"] buttonImage:@"login" buttonFrame:CGRectMake(kScreen_width/2 - 551/4, kScreen_height - 150, 551/2, 45)];


  • 講解

  • 頭文件
    /**
    *  選中page的指示器顏色,默認白色
    */
    @property (nonatomic, strong) UIColor *currentColor;
    /**
    *  其他狀態下的指示器的顏色,默認
    */
    @property (nonatomic, strong) UIColor *nomalColor;
    /**
    *  不帶按鈕的引導頁,滑動到最後一頁,再向右滑直接隱藏引導頁
    *
    *  @param imageNames 背景圖片數組
    *
    *  @return   LaunchIntroductionView對象
    */
    +(instancetype)sharedWithImages:(NSArray *) imageNames;
    /**
    *  帶按鈕的引導頁
    *
    *  @param imageNames      背景圖片數組
    *  @param buttonImageName 按鈕的圖片
    *  @param frame           按鈕的frame
    *
    *  @return LaunchIntroductionView對象
    */
    +(instancetype)sharedWithImages:(NSArray *) imageNames buttonImage:(NSString *) buttonImageName buttonFrame:(CGRect ) frame;
  • 核心實現
  • 實現原理
    創建一個UIView對象view,然後在view上添加一個scrollview,scrollview上添加需要的圖片及按鈕等,然後程序第一次啟動或者應用升級後把view添加到當前的window上,這樣view就顯示了出來,當滑動到最後或者點擊進入程序的按鈕時將view從window上移除,為了更好的體驗效果,在view移除時加了一個0.5s的動畫,產生了一個view漸漸消失的效果。
  • 詳細講解
    1、下面是調用接口的實現,均采用的是單例形式
    得益於i_Steven的一席話,已修改,詳情見文章底部的更新,不再使用單例的形式,也歡迎圍觀我的這篇文章單例的使用及避免對單例的濫用
    不帶按鈕時默認是滑動到最後時將引導頁隱藏
    #pragma mark - 創建單例-->>不帶button
    +(instancetype)sharedWithImages:(NSArray *)imageNames{
      static LaunchIntroductionView *launch = nil;
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
          images = imageNames;//背景數組
          isScrollOut = YES;//不帶按鈕時默認是滑動到最後時將引導頁隱藏
          launch = [[LaunchIntroductionView alloc] initWithFrame:CGRectMake(0, 0, kScreen_width, kScreen_height)];
          launch.backgroundColor = [UIColor whiteColor];
      });
      return launch;
    }
    帶按鈕時默認是點擊按鈕時將引導頁隱藏,滑動並不會隱藏引導頁,按鈕出現在最後一個頁面
    #pragma mark - 創建單例-->>帶button
    +(instancetype)sharedWithImages:(NSArray *)imageNames buttonImage:(NSString *)buttonImageName buttonFrame:(CGRect)frame{
      static LaunchIntroductionView *launch = nil;
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
          images = imageNames;
          isScrollOut = NO;//帶按鈕默認是點擊按鈕時將引導頁隱藏
          enterBtnFrame = frame;//button的frame
          enterBtnImage = buttonImageName;//button的圖片名字
          launch = [[LaunchIntroductionView alloc] initWithFrame:CGRectMake(0, 0, kScreen_width, kScreen_height)];
          launch.backgroundColor = [UIColor whiteColor];
      });
      return launch;
    }
    2、初始化時根據是不是首次啟動或者更新版本後首次啟動來判斷要不要添加引導頁到window上
    #pragma mark - 初始化
    -(instancetype)initWithFrame:(CGRect)frame
    {
      self = [super initWithFrame:frame];
      if (self) {
          //使用KVO監聽指示器顏色的變化
          [self addObserver:self forKeyPath:@"currentColor" options:NSKeyValueObservingOptionNew context:nil];
          [self addObserver:self forKeyPath:@"nomalColor" options:NSKeyValueObservingOptionNew context:nil];
          if ([self isFirstLauch]) {
              UIWindow *window = [[UIApplication sharedApplication] windows].lastObject;
              [window addSubview:self];
              [self addImages];
          }else{
              [self removeFromSuperview];
              self = nil;
          }
      }
      return self;
    }
    3、版本更新或者首次啟動的判斷
    #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;
      }
    }
    4、滾動視圖的創建就很簡單了,不具體再介紹,大家可以下載代碼看具體的實現,接下來主要說一下我在demo中遇到的稍微費點勁的問題:滾動方向的判斷
    demo中現在用的是這樣的判斷:
    #pragma mark - 判斷滾動方向
    -(BOOL )isScrolltoLeft:(UIScrollView *) scrollView{
      //返回YES為向左反動,NO為右滾動
      if ([scrollView.panGestureRecognizer translationInView:scrollView.superview].x < 0) {
          return YES;
      }else{
          return NO;
      }
    }
    其中translationInView的官方解釋是這樣的:

    translation in the coordinate system of the specified view

英文不太好,我的理解大概就是在一個特定view中的坐標,那麽到底是幹什麽用的呢?log一下看看,結果返現只要往左滑動屏幕,由

[scrollView.panGestureRecognizer translationInView:scrollView.superview].x

得到的值就為負數,反之則為正數,而且在手指觸摸的起始地方為坐標的(0,0)點,那麽好了,這樣我就能判斷左右滑動的方向了,然後就可以根據帶不帶button,在scrollview的delegate中在最後一個界面上來判斷要不要隱藏引導頁了:

#pragma mark - scrollView Delegate
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    int cuttentIndex = (int)(scrollView.contentOffset.x + kScreen_width/2)/kScreen_width;
    if (cuttentIndex == images.count - 1) {//保證是在最後一個頁面
        if ([self isScrolltoLeft:scrollView]) {//是否為左滑
            if (!isScrollOut) {//在設置為滑動不能隱藏引導頁的情況下直接返回
                return ;
            }
            [self hideGuidView];//反之在左滑成立的情況下隱藏引導頁
        }
    }
}

當然,並不是所有的事情看起來都那麽理所當然,我剛開始用到的判斷滑動方向的方法並不是這樣的,而是:

-(BOOL )isScrolltoLeft:(UIScrollView *) scrollView{
    BOOL ret = NO;
    static CGFloat newX = 0;
    static CGFloat oldX = 0;
    newX = scrollView.contentOffset.x;
    if (newX > oldX) {
        ret = YES;
    }else{
        ret = NO;
    }
    oldX = newX;
    return ret;//返回YES就是向左滑動,返貨NO就是向右滑動
}

根據scrollView的contentOffset來判斷,這樣做在scrollview的bounce為yes的情況下是完全沒問題的,bounce如果為NO在最後一個頁面是無法判斷作畫效果的,原因也很簡單,但卻讓我費了一番功夫,bounce為no的情況下,在最後一個頁面向左滑動時scrollview的contentOffset是不會發生發生辯護的,所以導致在無按鈕的情況下無論怎麽滑引導頁都不會隱藏,那bounce就設為yes不就行了?但是引導頁如果帶個bounce效果,那實在是讓人無法接受的,查找了多方資料才找到上面的那個方法,希望大家以後避免這個坑,少走彎路。


  • 詳細使用方法
    1、不帶按鈕、不定義指示器的顏色:
    [LaunchIntroductionView sharedWithImages:@[@"launch0.jpg",@"launch1.jpg",@"launch2.jpg",@"launch3"]];
    是的,就這麽一句代碼就搞定了,我們只需要傳入背景圖片即可。
    2、不帶按鈕,定制指示器的顏色:
      LaunchIntroductionView *launch = [LaunchIntroductionView sharedWithImages:@[@"launch0.jpg",@"launch1.jpg",@"launch2.jpg",@"launch3"]];
      launch.currentColor = [UIColor redColor];
      launch.nomalColor = [UIColor greenColor];
    3、帶按鈕、不定制指示器的顏色:
    [LaunchIntroductionView sharedWithImages:@[@"launch0.jpg",@"launch1.jpg",@"launch2.jpg",@"launch3"] buttonImage:@"login" buttonFrame:CGRectMake(kScreen_width/2 - 551/4, kScreen_height - 150, 551/2, 45)];
    傳的參數稍微多了點,不過也是應該並且值得的:背景圖片數組,進入應用的按鈕圖片,按鈕的frame,共三個參數
    4、帶按鈕,定制指示器的顏色
      LaunchIntroductionView *launch = [LaunchIntroductionView sharedWithImages:@[@"launch0.jpg",@"launch1.jpg",@"launch2.jpg",@"launch3"] buttonImage:@"login" buttonFrame:CGRectMake(kScreen_width/2 - 551/4, kScreen_height - 150, 551/2, 45)];
      launch.currentColor = [UIColor redColor];
      launch.nomalColor = [UIColor greenColor];

  • 附:

  • 下載鏈接:LaunchIntroductionDemo 下載地址:https://github.com/hungryBoy/LaunchIntroductionDemo

  • End

  • 更新1
    首先感謝i_Steven的意見,剛開始實現這個效果的時候想著用單例挺方便的,但隨之而來的內存問題確實是存在的,或許占得內存確實是不大的,但是這確實是一個問題,是問題就得改,於是我改了:

    #pragma mark - 創建對象-->>不帶button
    +(instancetype)sharedWithImages:(NSArray *)imageNames{
      images = imageNames;
      isScrollOut = YES;
      launch = [[LaunchIntroductionView alloc] initWithFrame:CGRectMake(0, 0, kScreen_width, kScreen_height)];
      launch.backgroundColor = [UIColor whiteColor];
      return launch;
    }
    #pragma mark - 創建對象-->>帶button
    +(instancetype)sharedWithImages:(NSArray *)imageNames buttonImage:(NSString *)buttonImageName buttonFrame:(CGRect)frame{
      images = imageNames;
      isScrollOut = NO;
      enterBtnFrame = frame;
      enterBtnImage = buttonImageName;
      launch = [[LaunchIntroductionView alloc] initWithFrame:CGRectMake(0, 0, kScreen_width, kScreen_height)];
      launch.backgroundColor = [UIColor whiteColor];
      return launch;
    }

    於是也催生了我這篇單例的使用及避免對單例的濫用文章,歡迎圍觀。

  • 更新2
    更新時間: 2017.01.12
    更新內容:添加storyboard支持

技術分享
使用storyboard時調用的方法

需要註意的是,如果項目不是使用的storyboard創建時調用此方法會導致crash。

IOS 一句代碼搞定啟動引導頁