更新:2017.11.14
更新內(nèi)容:
1.可以由在指定區(qū)域播放喉钢,并切換到全屏模式滑凉,然后點(diǎn)擊切換按鈕切換到以前指定區(qū)域
2.優(yōu)化橫豎屏切換的代碼以及WLPlayerControlView內(nèi)存管理引起的崩潰問題
要點(diǎn)說明:WLPlayerView新增了父視圖和父視圖原尺寸的屬性芽世,在初始化播放器的時(shí)候最盅,只需要將父視圖以及父視圖原尺寸保存起來葵蒂,在橫豎屏切換的時(shí)候調(diào)用分類提供的
- (void)makeScreenToLandscape;
- (void)makeScreenToPortrait;
這兩個(gè)方法就可以實(shí)現(xiàn)所需要的功能担敌,具體的調(diào)用邏輯可以查看源碼
做這款播放器還是因?yàn)轫?xiàng)目需要郭宝,關(guān)于播放器的需求辞槐,大都相同,要么是可以小屏全屏切換粘室,要么是一開始播放就默認(rèn)橫屏榄檬,由于下一個(gè)版本項(xiàng)目需求變化,需要的是一開始播放就默認(rèn)全屏播放衔统,之前我所用的是ZFPlayer鹿榜,這個(gè)庫很強(qiáng)大,基本上囊括了常用的功能點(diǎn)锦爵,特別是全屏切換這塊舱殿,這個(gè)庫處理的很好,但是遺憾的是這款播放器沒有提供自動(dòng)全屏的功能险掀,我在這個(gè)庫的源碼中修改之后能實(shí)現(xiàn)所要的效果沪袭,但是改動(dòng)了源碼總歸是不美的,于是我就花費(fèi)一些時(shí)間樟氢,參考這個(gè)庫冈绊,依據(jù)需求,先實(shí)現(xiàn)自己項(xiàng)目中的需要為準(zhǔn):實(shí)現(xiàn)已進(jìn)入就橫屏播放的需要埠啃。項(xiàng)目中用了RAC焚碌,以及Masnory布局方式。
我寫的這個(gè)庫目前還是初級(jí)階段霸妹,許多功能都不完善,主要包括以下幾個(gè)要點(diǎn):
1.present以及push進(jìn)入播放控制器知押,一進(jìn)入就橫屏
2.可以控制暫停/播放叹螟,雙擊屏幕暫停/播放,單擊屏幕顯示控制皮膚/隱藏控制皮膚等
3.滑動(dòng)播放進(jìn)度條可以控制播放時(shí)間台盯,跳轉(zhuǎn)到指定位置播放
4.橫屏豎屏切換功能罢绽,狀態(tài)欄方向跟著橫屏豎屏而變化等
5.左右滑動(dòng)屏幕,實(shí)現(xiàn)快進(jìn)/快退功能
6.上下滑動(dòng)右邊半屏静盅,控制系統(tǒng)音量良价,滑動(dòng)左半屏控制系統(tǒng)亮度
具體的功能模塊就以上幾個(gè)寝殴,是一個(gè)功能單一,比較簡(jiǎn)單的播放控制器明垢,我會(huì)在以后慢慢完善它的功能
下面我簡(jiǎn)要說一下如何去引用蚣常,并且對(duì)去全屏這塊做簡(jiǎn)要描述(只針對(duì)presetn下)
我先放兩張效果圖:
項(xiàng)目默認(rèn)是豎屏顯示,只有在播放界面才默認(rèn)橫屏:
從首頁進(jìn)入到播放界面如下處理:
@weakify(self);
[[self.playButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
@strongify(self);
WLPlayerController *playerC = [[WLPlayerController alloc] init];
[self presentViewController:playerC animated:YES completion:nil];
}];
在播放界面主要是控制進(jìn)入就橫屏顯示痊银,我是這樣處理的:
進(jìn)入播放器有兩種模式抵蚊,一種是present,一種是push溯革,我這里用的是tabbar+navigation+控制器的模式贞绳,默認(rèn)整個(gè)項(xiàng)目界面是豎屏,只有在播放界面才是橫屏致稀,下面我簡(jiǎn)要說明一下對(duì)于這兩種模式下的控制冈闭,我搜索資料有對(duì)這兩種區(qū)別去控制的,我也嘗試了下網(wǎng)上給的方法抖单,發(fā)現(xiàn)present很好弄萎攒,但是Push的坑很多,我這里是直接對(duì)兩種模式都有效果的臭猜,摘要代碼配置如下:
1.設(shè)置tabbarController分類躺酒,在分類中實(shí)現(xiàn)以下幾個(gè)方法
// 是否支持自動(dòng)轉(zhuǎn)屏
- (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];
}
}
// 默認(rèn)的屏幕方向(當(dāng)前ViewController必須是通過模態(tài)出來的UIViewController(模態(tài)帶導(dǎo)航的無效)方式展現(xiàn)出來的,才會(huì)調(diào)用這個(gè)方法)
- (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.設(shè)置導(dǎo)航控制器分類蔑歌,實(shí)現(xiàn)如下幾個(gè)方法:
- (BOOL)shouldAutorotate {
return self.topViewController.shouldAutorotate;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return self.topViewController.supportedInterfaceOrientations;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return self.topViewController.preferredInterfaceOrientationForPresentation;
}
3.所有的控制器繼承于這個(gè)基類羹应,在視頻播放控制器中單獨(dú)設(shè)置:
基類中默認(rèn)豎屏模式:
return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleDefault;
}
- (BOOL)prefersStatusBarHidden {
return NO;
}
播放器中如下設(shè)置:
// 支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeRight;
}
- (BOOL)prefersStatusBarHidden {
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight;
}
- (BOOL)shouldAutorotate {
return YES;
}
另外我在UIViewController的分類中提供了present和Push下實(shí)現(xiàn)橫屏和豎屏切換的方法,具體的方法如下:
- (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];
}
在這里我遇到一個(gè)坑次屠,改變狀態(tài)欄方向之后园匹,我一開始改變的是self.navigationController.view.bounds,結(jié)果會(huì)發(fā)現(xiàn)切換之間存在布局錯(cuò)亂劫灶,后來查了許久裸违,發(fā)現(xiàn)frame的x,y值出現(xiàn)負(fù)值,導(dǎo)致整體布局錯(cuò)亂本昏,于是我改成了改變frame值就解決了
具體的調(diào)用方式供汛,demo中有介紹,可以下載demo進(jìn)行嘗試與驗(yàn)證
關(guān)于其他的控制邏輯涌穆,在后續(xù)會(huì)進(jìn)一步實(shí)現(xiàn)怔昨,下面附上我的github源碼地址,有需要的伙伴們可以自行下載,使用過程遇到問題的歡迎留言評(píng)論宿稀,謝謝
特別說明:在適配iPad的時(shí)候趁舀,發(fā)現(xiàn)了一個(gè)重大問題,我所有設(shè)置強(qiáng)制豎屏的條件都不管用了祝沸,而且矮烹,在橫屏豎屏的時(shí)候混亂了越庇,經(jīng)查閱資料,最終解決了奉狈,解決方法是卤唉,將General->Deployment Info中的Requires Full Screen勾選選中