基于AVPlayer封裝的視頻播放器

更新:2017.11.14

更新內容:
1.可以由在指定區域播放,并切換到全屏模式,然后點擊切換按鈕切換到以前指定區域
2.優化橫豎屏切換的代碼以及WLPlayerControlView內存管理引起的崩潰問題

要點說明:WLPlayerView新增了父視圖和父視圖原尺寸的屬性,在初始化播放器的時候,只需要將父視圖以及父視圖原尺寸保存起來,在橫豎屏切換的時候調用分類提供的
- (void)makeScreenToLandscape;
- (void)makeScreenToPortrait;
這兩個方法就可以實現所需要的功能,具體的調用邏輯可以查看源碼

做這款播放器還是因為項目需要,關于播放器的需求,大都相同,要么是可以小屏全屏切換,要么是一開始播放就默認橫屏,由于下一個版本項目需求變化,需要的是一開始播放就默認全屏播放,之前我所用的是ZFPlayer,這個庫很強大,基本上囊括了常用的功能點,特別是全屏切換這塊,這個庫處理的很好,但是遺憾的是這款播放器沒有提供自動全屏的功能,我在這個庫的源碼中修改之后能實現所要的效果,但是改動了源碼總歸是不美的,于是我就花費一些時間,參考這個庫,依據需求,先實現自己項目中的需要為準:實現已進入就橫屏播放的需要。項目中用了RAC,以及Masnory布局方式。

我寫的這個庫目前還是初級階段,許多功能都不完善,主要包括以下幾個要點:

1.present以及push進入播放控制器,一進入就橫屏

2.可以控制暫停/播放,雙擊屏幕暫停/播放,單擊屏幕顯示控制皮膚/隱藏控制皮膚等

3.滑動播放進度條可以控制播放時間,跳轉到指定位置播放

4.橫屏豎屏切換功能,狀態欄方向跟著橫屏豎屏而變化等

5.左右滑動屏幕,實現快進/快退功能

6.上下滑動右邊半屏,控制系統音量,滑動左半屏控制系統亮度

具體的功能模塊就以上幾個,是一個功能單一,比較簡單的播放控制器,我會在以后慢慢完善它的功能
下面我簡要說一下如何去引用,并且對去全屏這塊做簡要描述(只針對presetn下)
我先放兩張效果圖:


Simulator Screen Shot - iPhone 6 Plus - 2017-11-13 at 10.28.38.png
Simulator Screen Shot - iPhone 6 Plus - 2017-11-13 at 10.28.47.png

項目默認是豎屏顯示,只有在播放界面才默認橫屏:
從首頁進入到播放界面如下處理:

@weakify(self);
    [[self.playButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
        @strongify(self);
        WLPlayerController *playerC = [[WLPlayerController alloc] init];
        [self presentViewController:playerC animated:YES completion:nil];
    }];

在播放界面主要是控制進入就橫屏顯示,我是這樣處理的:

進入播放器有兩種模式,一種是present,一種是push,我這里用的是tabbar+navigation+控制器的模式,默認整個項目界面是豎屏,只有在播放界面才是橫屏,下面我簡要說明一下對于這兩種模式下的控制,我搜索資料有對這兩種區別去控制的,我也嘗試了下網上給的方法,發現present很好弄,但是Push的坑很多,我這里是直接對兩種模式都有效果的,摘要代碼配置如下:

1.設置tabbarController分類,在分類中實現以下幾個方法

// 是否支持自動轉屏
- (BOOL)shouldAutorotate {
    UIViewController *vc = self.viewControllers[self.selectedIndex];
    if ([vc isKindOfClass:[UINavigationController class]]) {
        UINavigationController *nav = (UINavigationController *)vc;
        return [nav.topViewController shouldAutorotate];
    } else {
        return [vc shouldAutorotate];
    }
}

// 支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    UIViewController *vc = self.viewControllers[self.selectedIndex];
    if ([vc isKindOfClass:[UINavigationController class]]) {
        UINavigationController *nav = (UINavigationController *)vc;
        return [nav.topViewController supportedInterfaceOrientations];
    } else {
        return [vc supportedInterfaceOrientations];
    }
}

// 默認的屏幕方向(當前ViewController必須是通過模態出來的UIViewController(模態帶導航的無效)方式展現出來的,才會調用這個方法)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    UIViewController *vc = self.viewControllers[self.selectedIndex];
    if ([vc isKindOfClass:[UINavigationController class]]) {
        UINavigationController *nav = (UINavigationController *)vc;
        return [nav.topViewController preferredInterfaceOrientationForPresentation];
    } else {
        return [vc preferredInterfaceOrientationForPresentation];
    }
}

2.設置導航控制器分類,實現如下幾個方法:

- (BOOL)shouldAutorotate {
    return self.topViewController.shouldAutorotate;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return self.topViewController.supportedInterfaceOrientations;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return self.topViewController.preferredInterfaceOrientationForPresentation;
}

3.所有的控制器繼承于這個基類,在視頻播放控制器中單獨設置:
基類中默認豎屏模式:

    return YES;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}
- (UIStatusBarStyle)preferredStatusBarStyle {
    return  UIStatusBarStyleDefault;
}
- (BOOL)prefersStatusBarHidden {
    return NO;
}

播放器中如下設置:


// 支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeRight;
}

- (BOOL)prefersStatusBarHidden {
    return NO;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeRight;
}

- (BOOL)shouldAutorotate {
    return YES;
}

另外我在UIViewController的分類中提供了present和Push下實現橫屏和豎屏切換的方法,具體的方法如下:

- (void)makeScreenToLandscape {
    [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeRight;
    CGFloat duration = [UIApplication sharedApplication].statusBarOrientationAnimationDuration;
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:duration];
    if (self.navigationController) {
        self.view.transform = CGAffineTransformMakeRotation(M_PI*(90)/180.0);
        self.view.frame = CGRectMake(0, 0,  [UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
    }else {
        self.view.transform = CGAffineTransformIdentity;
        self.view.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
    }
    [UIView commitAnimations];
    [[NSNotificationCenter defaultCenter] postNotificationName:wl_makeScreenToLandscapeNotificationName object:nil];
}
- (void)makeScreenToPortrait {
    [UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait;
    CGFloat duration = [UIApplication sharedApplication].statusBarOrientationAnimationDuration;
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:duration];
    if (self.navigationController) {
        self.view.transform = CGAffineTransformIdentity;
        self.view.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
    }else {
        self.view.transform = CGAffineTransformMakeRotation(-M_PI*(90)/180.0);
        self.view.frame = CGRectMake(0, 0,  [UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
    }
    [UIView commitAnimations];
    [[NSNotificationCenter defaultCenter] postNotificationName:wl_makeScreenToPortraitNotificationName object:nil];
}

在這里我遇到一個坑,改變狀態欄方向之后,我一開始改變的是self.navigationController.view.bounds,結果會發現切換之間存在布局錯亂,后來查了許久,發現frame的x,y值出現負值,導致整體布局錯亂,于是我改成了改變frame值就解決了

具體的調用方式,demo中有介紹,可以下載demo進行嘗試與驗證

關于其他的控制邏輯,在后續會進一步實現,下面附上我的github源碼地址,有需要的伙伴們可以自行下載,使用過程遇到問題的歡迎留言評論,謝謝

特別說明:在適配iPad的時候,發現了一個重大問題,我所有設置強制豎屏的條件都不管用了,而且,在橫屏豎屏的時候混亂了,經查閱資料,最終解決了,解決方法是,將General->Deployment Info中的Requires Full Screen勾選選中

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,229評論 4 61
  • 8月7日迎來今年的立秋節氣,立秋一般預示著炎熱的夏天即將過去,秋天即將來臨。立秋(節氣)以后,秋后下一次雨涼快一次...
    引領緣夢閱讀 253評論 0 0
  • 昨夜在漫散的睡意中我想起了外公,外公年事已高,有些糊涂了,也不如往常那般與我親切。這幾年回家的次數越來越少,每...
    你不知道的Anne閱讀 376評論 1 2
  • 零度打卡Day24 主題閱讀:精進之道 采銅的精進之道 導圖筆記之一: 導圖筆記之二: 努力一點,是為了看清自己最...
    零度2013閱讀 184評論 0 0