iOS App啟動(dòng)圖--視頻

這篇文章要介紹的是李剖,在軟件啟動(dòng)的時(shí)候,呈現(xiàn)一個(gè)視頻播放功能囤耳,目前主流的社交App啟動(dòng)時(shí)都有這樣的功能篙顺,效果還蠻不錯(cuò)的崔慧。

目標(biāo)

這里要實(shí)現(xiàn)的功能是凑兰,第一次進(jìn)入軟件,啟動(dòng)時(shí)播放一段較長(zhǎng)的視頻湃窍,并且有進(jìn)入應(yīng)用按鈕,不點(diǎn)擊按鈕會(huì)一直循環(huán)播放視頻椎麦,直到點(diǎn)擊按鈕才會(huì)跳轉(zhuǎn)到應(yīng)用內(nèi)部;如果是第二次進(jìn)入軟件宰僧,則啟動(dòng)時(shí)播放一段較短的視頻,播放完成直接進(jìn)入到應(yīng)用內(nèi)部观挎,且沒有進(jìn)入應(yīng)用按鈕

細(xì)節(jié)實(shí)現(xiàn)
1.怎樣在啟動(dòng)時(shí)進(jìn)入視頻播放琴儿,在需要結(jié)束播放時(shí)退出視頻播放

軟件啟動(dòng)過程中,會(huì)最先顯示LaunchScreen.storyboard嘁捷,然后都會(huì)走AppDelegate中的方法:- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions造成。所以

  • 可以創(chuàng)建一個(gè)用于視頻播放的控制器(下面說成AV控制器),在這個(gè)代理方法中將AV控制器雄嚣,設(shè)置為根控制器晒屎,這樣就可以進(jìn)入視頻播放了
  • 在需要結(jié)束播放的地方(點(diǎn)擊事件或者播放完成),將需要顯示的控制器設(shè)置為窗口的根控制器缓升,這樣就可以退出了
2.流暢性能處理---視頻播放中斷和剛開始播放時(shí)插入圖片
  • 從LaunchScreen.storyboard到視頻播放鼓鲁,會(huì)有一個(gè)間斷,在這個(gè)地方添加一張圖片港谊,圖片內(nèi)容就和LaunchScreen.storyboard中的一樣骇吭,然后LaunchScreen.storyboard中的圖片和視頻的第一幀一樣,這樣的話畫面看起來(lái)就比較流暢了
  • 開始播放后封锉,會(huì)有一個(gè)自帶的通知--AVPlayerItemTimeJumpedNotification绵跷,添加觀察者,在觀察者的事件中成福,移除開始播放前插入的圖片
  • 點(diǎn)擊進(jìn)入應(yīng)用按鈕碾局,視頻播放中斷,跳轉(zhuǎn)到應(yīng)用界面中間會(huì)有個(gè)停頓奴艾,在這里添加一個(gè)圖片净当,圖片就是當(dāng)前界面的截圖,只需要很短的時(shí)間即可蕴潦,這樣看起來(lái)就比較流暢了
3.第一次進(jìn)入和非第一次進(jìn)入軟件的處理
  • 第一次進(jìn)入像啼,會(huì)有進(jìn)入應(yīng)用按鈕,并且潭苞,不點(diǎn)擊則循環(huán)播放視頻忽冻;而非第一次進(jìn)入,則直接播放另一個(gè)較短的視頻此疹,播放完成僧诚,則跳轉(zhuǎn)到應(yīng)用。根據(jù)這個(gè)區(qū)別蝗碎,添加一個(gè)布爾值的屬性湖笨,通過[NSUserDefaults standardUserDefaults]來(lái)記錄是否為第一次進(jìn)入應(yīng)用,然后進(jìn)行相關(guān)處理蹦骑。
  • 視頻播放完成自帶有這個(gè)通知--AVPlayerItemDidPlayToEndTimeNotification慈省,添加觀察者,第一次進(jìn)入軟件時(shí)眠菇,視頻播放完成边败,在觀察者的事件中,再次播放視頻捎废;第二次進(jìn)入軟件時(shí)放闺,視頻播放完成,在觀察者的事件中缕坎,直接進(jìn)入應(yīng)用怖侦。

上代碼
創(chuàng)建視頻控制器AVPlayerVC,繼承自AVPlayerViewController,可能剛創(chuàng)建會(huì)報(bào)錯(cuò)谜叹,需要引入AVKit框架---#import <AVKit/AVKit.h>匾寝,就不會(huì)報(bào)錯(cuò)了

#import <AVKit/AVKit.h>

@interface AVPlayerVC : AVPlayerViewController

@end

在AppDelegate中引入AVPlayerVC控制器,并設(shè)置根控制器

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.rootViewController = [[AVPlayerVC alloc] init];
    [self.window makeKeyAndVisible];
    // Override point for customization after application launch.
    return YES;
}

在視頻播放器中添加屬性

@interface AVPlayerVC ()
//播放開始之前的圖片
@property(nonatomic,strong)UIImageView * startPlayerImageView;
//播放中斷時(shí)的圖片
@property(nonatomic,strong)UIImageView * pausePlayerImageView;
//進(jìn)入應(yīng)用按鈕
@property(nonatomic,strong)UIButton * enterMainButton;
//是否第一次進(jìn)入App
@property(nonatomic,assign)BOOL isFirstLunchApp;
@end

用到的宏和頭文件

#import <AVFoundation/AVFoundation.h>
#import "ViewController.h"
#import "AppDelegate.h"
#define kScreenHeight [UIScreen mainScreen].bounds.size.height
#define kScreenWidth [UIScreen mainScreen].bounds.size.width
#define kIsFirstLunchApp @"isFirstLunchApp"

因?yàn)橛玫酵ㄖ衫埃筒シ牌餮藁冢韵仍赿ealloc方法中將其注銷

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    if (self.player) {
        self.player = nil;
    }
}

初始化視圖、添加通知女仰、初始化播放器

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initView];
}
#pragma mark -- 初始化視圖
-(void)initView{
    //添加一個(gè)圖片猜年,在視頻播放之前放一張圖片抡锈,這張圖片和LunchScreen.storyboard中的相同,這樣的話效果看起來(lái)連貫
    self.startPlayerImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"lauch"]];
    self.startPlayerImageView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
    [self.contentOverlayView addSubview:self.startPlayerImageView];
    /*對(duì)于contentOverlayView 官方解釋是這樣的:A view displayed between the video content and the playback controls.*/
    //第一次進(jìn)入軟件播放長(zhǎng)一點(diǎn)的視頻,并且?guī)в小斑M(jìn)入應(yīng)用的按鈕”乔外;第二次進(jìn)入軟件播放短一點(diǎn)的視頻床三,并且無(wú)進(jìn)入按鈕
    self.isFirstLunchApp = [[NSUserDefaults standardUserDefaults] boolForKey:kIsFirstLunchApp];
    if (!self.isFirstLunchApp) {//第一次啟動(dòng)軟件
        //添加“進(jìn)入應(yīng)用”按鈕
        [self addEnterButton];
    }
    //添加監(jiān)聽通知
    [self addNotification];
    //初始化視頻
    [self prepareAV];
}
-(void)addEnterButton{
    self.enterMainButton = [UIButton buttonWithType:UIButtonTypeCustom];
    _enterMainButton.frame = CGRectMake(24, kScreenHeight - 32 - 48, kScreenWidth - 48, 48);
    _enterMainButton.layer.borderWidth =1;
    _enterMainButton.layer.cornerRadius = 24;
    _enterMainButton.layer.borderColor = [UIColor whiteColor].CGColor;
    [_enterMainButton setTitle:@"進(jìn)入應(yīng)用" forState:UIControlStateNormal];
    [self.view addSubview:_enterMainButton];
    [_enterMainButton addTarget:self action:@selector(enterMainAction:) forControlEvents:UIControlEventTouchUpInside];
    _enterMainButton.hidden = YES;//先設(shè)置為隱藏,等過三秒的時(shí)間在顯示該按鈕杨幼,
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        _enterMainButton.hidden = NO;
    });
}
//添加通知
-(void)addNotification{
    //添加播放器的幾個(gè)通知--1.播放開始的時(shí)候撇簿,要?jiǎng)h掉開始的占位圖,如果是第一次進(jìn)入應(yīng)用差购,在沒有點(diǎn)擊“進(jìn)入應(yīng)用”時(shí)四瘫,需要循環(huán)播放
    if (self.isFirstLunchApp) {
        //第二次進(jìn)入app視頻需要直接結(jié)束
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlaybackComplete) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];//視頻播放結(jié)束時(shí)添加通知
    }else {
        //第一次進(jìn)入app視頻需要輪播
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlaybackAgain) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];//視頻播放結(jié)束時(shí)添加通知
    }
    //播放開始
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlaybackStart) name:AVPlayerItemTimeJumpedNotification object:nil];
}
//初始化播放器
-(void)prepareAV{
    //首次運(yùn)行
    NSString *filePath = nil;
    if (!self.isFirstLunchApp) {//沒有值,說明是第一次
        //第一次安裝
        filePath = [[NSBundle mainBundle] pathForResource:@"opening_long_1080*1920.mp4" ofType:nil];
        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kIsFirstLunchApp];
    }else {
        filePath = [[NSBundle mainBundle] pathForResource:@"opening_short_1080*1920.mp4" ofType:nil];
    }
    //初始化player
    self.player = [AVPlayer playerWithURL:[NSURL fileURLWithPath:filePath]];
    self.showsPlaybackControls = NO;
    //播放視頻
    [self.player play];
}

點(diǎn)擊事件和通知事件

#pragma mark -- 點(diǎn)擊事件及通知事件
//進(jìn)入按鈕點(diǎn)擊事件
-(void)enterMainAction:(UIButton*)sender{
    //暫停播放
    [self.player pause];
    //添加一個(gè)imageView,用于放置暫停播放時(shí)的圖片
    self.pausePlayerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)];
    [self.contentOverlayView addSubview:self.pausePlayerImageView];
    self.pausePlayerImageView.contentMode = UIViewContentModeScaleAspectFit;//設(shè)置
    //截圖并展示截圖
    [self getoverPlayerImage];
    //播放結(jié)束要移除相關(guān)的對(duì)象
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self moviePlaybackComplete];
    });
    
}
//結(jié)束播放刪除對(duì)應(yīng)的對(duì)象和注銷通知事件
-(void)moviePlaybackComplete{
    //移除播放前的占位圖
    [self.startPlayerImageView removeFromSuperview];
    self.startPlayerImageView = nil;
    //移除暫停播放的占位圖
    [self.pausePlayerImageView removeFromSuperview];
    self.pausePlayerImageView = nil;
    //跳轉(zhuǎn)到新界面
    [self pushToNewController];
}
//循環(huán)播放事件
-(void)moviePlaybackAgain{
    //添加播放前的占位圖
    self.startPlayerImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"lauchAgain"]];
    _startPlayerImageView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
    [self.contentOverlayView addSubview:_startPlayerImageView];
    [self.pausePlayerImageView removeFromSuperview];
    self.pausePlayerImageView = nil;
    //初始化player
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"opening_long_1080*1920.mp4" ofType:nil];
    self.player = [AVPlayer playerWithURL:[NSURL fileURLWithPath:filePath]];
    self.showsPlaybackControls = NO;
    //播放視頻
    [self.player play];
}
//開始播放通知事件
- (void)moviePlaybackStart {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.startPlayerImageView removeFromSuperview];
        self.startPlayerImageView = nil;
    });
}

私有方法

#pragma mark -- 私有方法
//獲取截圖
- (void)getoverPlayerImage {
    AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:self.player.currentItem.asset];
    gen.appliesPreferredTrackTransform = YES;
    NSError *error = nil;
    CMTime actualTime;
    CMTime now = self.player.currentTime;
    [gen setRequestedTimeToleranceAfter:kCMTimeZero];
    [gen setRequestedTimeToleranceBefore:kCMTimeZero];
    CGImageRef image = [gen copyCGImageAtTime:now actualTime:&actualTime error:&error];
    if (!error) {
        UIImage *thumb = [[UIImage alloc] initWithCGImage:image];
        self.pausePlayerImageView.image = thumb;
    }
    NSLog(@"%f , %f",CMTimeGetSeconds(now),CMTimeGetSeconds(actualTime));
    NSLog(@"%@",error);
}
//跳轉(zhuǎn)到新的控制器
-(void)pushToNewController{
    AppDelegate * appde = (AppDelegate*)[UIApplication sharedApplication].delegate;
    UIViewController * mainC = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateInitialViewController];
    appde.window.rootViewController = mainC;
    [appde.window makeKeyWindow];
}

Demo下載
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末欲逃,一起剝皮案震驚了整個(gè)濱河市找蜜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌稳析,老刑警劉巖锹杈,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異迈着,居然都是意外死亡竭望,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門裕菠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)咬清,“玉大人,你說我怎么就攤上這事奴潘【缮眨” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵画髓,是天一觀的道長(zhǎng)掘剪。 經(jīng)常有香客問我,道長(zhǎng)奈虾,這世上最難降的妖魔是什么夺谁? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮肉微,結(jié)果婚禮上匾鸥,老公的妹妹穿的比我還像新娘。我一直安慰自己碉纳,他們只是感情好勿负,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著劳曹,像睡著了一般奴愉。 火紅的嫁衣襯著肌膚如雪琅摩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天锭硼,我揣著相機(jī)與錄音房资,去河邊找鬼。 笑死账忘,一個(gè)胖子當(dāng)著我的面吹牛志膀,可吹牛的內(nèi)容都是我干的熙宇。 我是一名探鬼主播鳖擒,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼烫止!你這毒婦竟也來(lái)了蒋荚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤馆蠕,失蹤者是張志新(化名)和其女友劉穎期升,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體互躬,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡播赁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吼渡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片容为。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖寺酪,靈堂內(nèi)的尸體忽然破棺而出坎背,到底是詐尸還是另有隱情,我是刑警寧澤寄雀,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布得滤,位于F島的核電站,受9級(jí)特大地震影響盒犹,放射性物質(zhì)發(fā)生泄漏懂更。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一急膀、第九天 我趴在偏房一處隱蔽的房頂上張望膜蛔。 院中可真熱鬧,春花似錦脖阵、人聲如沸皂股。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)呜呐。三九已至就斤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蘑辑,已是汗流浹背洋机。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留洋魂,地道東北人绷旗。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像副砍,于是被迫代替她去往敵國(guó)和親衔肢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容