iOS9之前使用MediaPlayer來(lái)進(jìn)行視頻的播放,iOS9之后系統(tǒng)推薦使用AVFoundation框架實(shí)現(xiàn)視頻的播放,兩者的使用都是比較簡(jiǎn)單,但是之前使用MediaPlayer播放的時(shí)候好像沒能實(shí)現(xiàn)跟優(yōu)酷視頻(或者其他視頻)一樣全屏。
1澳淑、首先定義AVPlayer、AVPlayerLayer插佛、AVPlayerItem并初始化杠巡,定義一個(gè)UIView,用于存儲(chǔ)AVPlayerLayer
@property (strong, nonatomic) AVPlayer *avPlayer;
@property (strong, nonatomic) AVPlayerLayer *avPlayerLayer;
@property (strong, nonatomic) AVPlayerItem *playerItem;
@property (strong, nonatomic) UIView *imageView;
// 初始化player 和playerLayer
self.avPlayer = [[AVPlayer alloc]init];
self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 200.0)];
self.imageView.userInteractionEnabled = YES;
self.imageView.backgroundColor = [UIColor blackColor];
[self.view addSubview:self.imageView];
// imageView上添加playerLayer
[self.imageView.layer addSublayer:self.avPlayerLayer];
self.avPlayerLayer.frame = self.imageView.bounds;
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
self.playerItem = [AVPlayerItem playerItemWithURL:url];
[self.avPlayer replaceCurrentItemWithPlayerItem:self.playerItem];
播放API
[self.avPlayer play];
暫停API
[self.avPlayer pause];
重播API
[self.avPlayer replaceCurrentItemWithPlayerItem:self.playerItem];
以上代碼基本上可以實(shí)現(xiàn)視頻播放了朗涩,但是例如優(yōu)酷播放視頻里還有進(jìn)度條顯示之類的忽孽,類似下面的效果。
2谢床、其他控件定義
@property (strong, nonatomic) UIView *showTime;
@property (strong, nonatomic) UIButton *buttonFull;
@property (strong, nonatomic) UIView *maskView;
@property (strong, nonatomic) UIButton *replayBtn;
@property (strong, nonatomic) UILabel *timeLabel;
@property (strong, nonatomic) UILabel *allTimeLabel;
@property (strong, nonatomic) UISlider *slider;
@property (strong, nonatomic) NSTimer *progressTimer;
@property (strong, nonatomic) UIButton *playOrPauseBtn;
3兄一、實(shí)現(xiàn)進(jìn)度條效果
一下實(shí)現(xiàn)進(jìn)度條頁(yè)面的主要代碼
- (UIView *)showTime{
if (_showTime == nil) {
_showTime = [[UIView alloc] init];
_showTime.backgroundColor = [UIColor colorWithWhite:1 alpha:0.0];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"full_play_btn_hl"] forState:UIControlStateNormal];
button.frame = CGRectMake(10, 5, 30, 30);
[button setImage:[UIImage imageNamed:@"full_pause_btn"] forState:UIControlStateSelected];
[button addTarget:self action:@selector(player:) forControlEvents:UIControlEventTouchUpInside];
[_showTime addSubview:button];
_playOrPauseBtn = button;
UIButton *buttonFull = [UIButton buttonWithType:UIButtonTypeCustom];
[buttonFull setImage:[UIImage imageNamed:@"mini_launchFullScreen_btn_hl"] forState:UIControlStateNormal];
[buttonFull setImage:[UIImage imageNamed:@"full_minimize_btn_hl"] forState:UIControlStateSelected];
[buttonFull addTarget:self action:@selector(fullScreen:) forControlEvents:UIControlEventTouchUpInside];
[_showTime addSubview:buttonFull];
_buttonFull = buttonFull;
_timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(button.frame) + 10.0, 0, 40.0, 40.0)];
_timeLabel.textColor = [UIColor whiteColor];
_timeLabel.font = [UIFont systemFontOfSize:14.0];
[_showTime addSubview:_timeLabel];
_allTimeLabel = [[UILabel alloc] init];
_allTimeLabel.textColor = [UIColor whiteColor];
_allTimeLabel.font = [UIFont systemFontOfSize:14.0];
[_showTime addSubview:_allTimeLabel];
_slider = [[UISlider alloc] init];
_slider.tintColor = [UIColor redColor];
[_slider setThumbImage:[UIImage imageNamed:@"thumbImage"] forState:UIControlStateNormal];
[_slider addTarget:self action:@selector(touchDownSlider:) forControlEvents:UIControlEventTouchDown];
[_slider addTarget:self action:@selector(valueChangedSlider:) forControlEvents:UIControlEventValueChanged];
[_slider addTarget:self action:@selector(touchUpInside:) forControlEvents:UIControlEventTouchUpInside];
[_showTime addSubview:_slider];
[self setShowTimeFrame];
}
return _showTime;
}
frame布局
- (void)setShowTimeFrame{
self.showTime.frame = CGRectMake(0, self.imageView.frame.size.height-40.0, [UIScreen mainScreen].bounds.size.width, 40);
self.buttonFull.frame = CGRectMake(_showTime.frame.size.width-30-10, 5, 30, 30);
self.maskView.frame = self.imageView.bounds;
self.replayBtn.center = self.maskView.center;
self.allTimeLabel.frame = CGRectMake([UIScreen mainScreen].bounds.size.width-45-40, 0, 40.0, 40.0);
self.slider.frame = CGRectMake(0, 0, _showTime.frame.size.width, 1);
}
- (UIView *)maskView{
if (_maskView == nil) {
_maskView = [[UIView alloc] init];
_replayBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_replayBtn setImage:[UIImage imageNamed:@"player"] forState:UIControlStateNormal];
[_replayBtn setImage:[UIImage imageNamed:@"chongbo"] forState:UIControlStateSelected];
[_replayBtn addTarget:self action:@selector(resetPlay:) forControlEvents:UIControlEventTouchUpInside];
_replayBtn.bounds = CGRectMake(0, 0, 50, 50);
[_maskView addSubview:_replayBtn];
}
return _maskView;
}
4、實(shí)現(xiàn)定時(shí)功能识腿,進(jìn)度條滾動(dòng)
定時(shí)器主要用于進(jìn)度條的滾動(dòng)出革,這里的NSRunLoop使用NSRunLoopCommonModes,這樣的話如果使用tableView的話渡讼,當(dāng)tableView滾動(dòng)時(shí)視頻還能繼續(xù)播放骂束。
- (NSTimer *)progressTimer{
if (_progressTimer == nil) {
_progressTimer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updateProgressInfo) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:_progressTimer forMode:NSRunLoopCommonModes];
}
return _progressTimer;
}
/** 移除定時(shí)器 */
-(void)removeProgressTimer{
[self.progressTimer invalidate];
self.progressTimer = nil;
}
5、實(shí)現(xiàn)進(jìn)度條功能
開始拖動(dòng)時(shí)成箫,要移除定時(shí)監(jiān)聽器
/** slider拖動(dòng)和點(diǎn)擊事件 */
- (void)touchDownSlider:(UISlider *)sender {
// 按下去 移除監(jiān)聽器
[self removeProgressTimer];
}
- (void)valueChangedSlider:(UISlider *)sender {
// 計(jì)算slider拖動(dòng)的點(diǎn)對(duì)應(yīng)的播放時(shí)間
NSTimeInterval currentTime = CMTimeGetSeconds(self.avPlayer.currentItem.duration) * sender.value;
self.timeLabel.text = [self timeToStringWithTimeInterval:currentTime];
}
- (void)touchUpInside:(UISlider *)sender {
[self progressTimer];
//計(jì)算當(dāng)前slider拖動(dòng)對(duì)應(yīng)的播放時(shí)間
NSTimeInterval currentTime = CMTimeGetSeconds(self.avPlayer.currentItem.duration) * sender.value;
// 播放移動(dòng)到當(dāng)前播放時(shí)間
[self.avPlayer seekToTime:CMTimeMakeWithSeconds(currentTime, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
// [self addShowTime];
}
6展箱、定時(shí)器方法
/** 轉(zhuǎn)換播放時(shí)間和總時(shí)間的方法 */
-(NSString *)timeToStringWithTimeInterval:(NSTimeInterval)interval;{
NSInteger Min = interval / 60;
NSInteger Sec = (NSInteger)interval % 60;
NSString *intervalString = [NSString stringWithFormat:@"%02ld:%02ld",Min,Sec];
return intervalString;
}
/** 更新slider和timeLabel */
- (void)updateProgressInfo {
NSTimeInterval currentTime = CMTimeGetSeconds(self.avPlayer.currentTime);
NSTimeInterval durationTime = CMTimeGetSeconds(self.avPlayer.currentItem.duration);
self.timeLabel.text = [self timeToStringWithTimeInterval:currentTime];
self.allTimeLabel.text = [self timeToStringWithTimeInterval:durationTime];
self.slider.value = CMTimeGetSeconds(self.avPlayer.currentTime) / CMTimeGetSeconds(self.avPlayer.currentItem.duration);
if (self.slider.value == 1) {
[self removeProgressTimer];
self.replayBtn.selected = YES;
self.maskView.hidden = NO;
self.replayBtn.hidden = NO;
NSLog(@"播放完了");
}
}
7、播放和暫停視頻播放
這里的maskView主要是用于顯示
/** 播放暫停 */
- (void)player:(UIButton *)sender{
if (sender.selected == YES) {//暫停
[self.avPlayer pause];
[self removeProgressTimer];
self.maskView.hidden = NO;
self.replayBtn.hidden = NO;
self.replayBtn.selected = NO;
}else{
self.replayBtn.selected = YES;
self.maskView.hidden = YES;
self.replayBtn.hidden = YES;
[self progressTimer];
[self.avPlayer play];
}
sender.selected = !sender.selected;
}
8蹬昌、全屏播放
全屏播放主要是當(dāng)前控制器present到另一個(gè)控制器
新建控制器混驰,并修改控制器的方向
下面是全屏控制器,修改控制器方面的代碼
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return YES;
}
/** 全屏按鈕 */
- (void)fullScreen:(UIButton *)sender{
if (sender.selected == NO) {
[self presentViewController:self.fullVc animated:NO completion:^{
[self.fullVc.view addSubview:self.imageView];
self.imageView.center = self.fullVc.view.center;
[UIView animateWithDuration:0.15 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^{
self.imageView.frame = self.fullVc.view.bounds;
[self layoutFrame];
[self fullscreenOrNotFullScreen];
} completion:nil];
}];
}else{
[self.fullVc dismissViewControllerAnimated:NO completion:^{
[self.view addSubview:self.imageView];
[UIView animateWithDuration:0.15 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^{
self.imageView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 200.0);
[self layoutFrame];
[self fullscreenOrNotFullScreen];
} completion:nil];
}];
}
sender.selected = !sender.selected;
}
- (void)fullscreenOrNotFullScreen{
self.replayBtn.selected = NO;
[self resetPlay:_replayBtn];
}
下面是非全屏播放控制器設(shè)置控制器方向
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return NO;
}
9皂贩、重新播放
視頻播放完成之后栖榨,點(diǎn)擊按鈕重新播放
/** 重新播放 */
- (void)resetPlay:(UIButton *)sender{
if (sender.isSelected) {
self.slider.value = 0.0;
self.playOrPauseBtn.selected = YES;
[self.avPlayer replaceCurrentItemWithPlayerItem:self.playerItem];
//計(jì)算當(dāng)前slider拖動(dòng)對(duì)應(yīng)的播放時(shí)間
NSTimeInterval currentTime = CMTimeGetSeconds(self.avPlayer.currentItem.duration) * self.slider.value;
// 播放移動(dòng)到當(dāng)前播放時(shí)間
[self.avPlayer seekToTime:CMTimeMakeWithSeconds(currentTime, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}else{
self.playOrPauseBtn.selected = YES;
}
[self removeProgressTimer];
[self.avPlayer play];
[self progressTimer];
sender.selected = YES;
sender.hidden = YES;
self.maskView.hidden = YES;
}
注意:當(dāng)最初當(dāng)前控制器的之后記得要移除監(jiān)聽器和停止播放
[self removeProgressTimer];
[self.avPlayer pause];
目前demo在cocoaChina審核中,等審核通過(guò)會(huì)貼上網(wǎng)址