寫在前面
弄了下個人站...防止內(nèi)容再次被鎖定...所有東西都在這里面
welcome~
個人博客
大致效果
不要介意。界面有點丑枪狂。危喉。。
界面搭建
看下成員變量就知道我怎么搭建的了,這里我將video播放層的size作為參照量州疾,對所有控件的size按照其video的size寬高進行比例縮放
@interface VideoPlayerView()
@property (nonatomic,copy) NSString *path; //播放地址 自動判斷文件路徑和網(wǎng)址路徑
@property (nonatomic,strong) AVPlayer *player; //播放類
@property (nonatomic,strong) AVPlayerLayer *playerlayer; //顯示區(qū)域
@property (nonatomic,strong) UIButton *playBtn; //播放暫停
@property (nonatomic,strong) UIButton *stopBtn; // 停止
@property (nonatomic,strong) UIButton *fullScreenBtn; //全屏
@property (nonatomic,strong) UISlider *playSlider; //進度選擇
@property (nonatomic,strong) UIProgressView *progress; //進度
@property (nonatomic,strong) UILabel *currentTimeLab; //當前時間
@property (nonatomic,strong) UILabel *durationLab; //總時間
@property (nonatomic,strong) UIView *toolView; //工具欄view
@property (nonatomic,assign) BOOL isFullScreen; //全屏判斷
@property (nonatomic,assign) CGFloat videoHeight; //video高
@property (nonatomic,assign) CGFloat videoWidth; //video寬
@end
所有控件使用懶加載 如下
//播放暫停
- (UIButton *)playBtn {
if (!_playBtn) {
_playBtn = [[UIButton alloc] initWithFrame:CGRectMake(kLrMargin, kUIy, kBtnWidth, kUIHeight)];
_playBtn.backgroundColor =[UIColor greenColor];
_playBtn.selected = NO;
_playBtn.enabled = NO;
_playBtn.titleLabel.adjustsFontSizeToFitWidth = YES;
[_playBtn setTitle:@"播放" forState:UIControlStateNormal];
[_playBtn setTitle:@"暫停" forState:UIControlStateSelected];
[_playBtn addTarget:self action:@selector(play) forControlEvents:UIControlEventTouchUpInside];
}
return _playBtn;
}
屏幕適配
由于涉及到屏幕的旋轉(zhuǎn)和適配辜限。我這里沒有使用第三方框架來做約束,而是使用最基本的按百分比設置frame严蓖。旋轉(zhuǎn)屏幕時通過調(diào)用本類- (void)resetFrame:(CGSize)size;
方法來重設frame薄嫡。所以需要重設frame的控件在懶加載中設置frame氧急,調(diào)用時即刷新frame。
- 先看下初始化 對video的size設置是時始終用最小的邊來確定高度毫深,寬度與屏幕當前寬度相當
//初始化
- (instancetype)initWithFrame:(CGRect)frame andPath:(NSString*)path {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
self.path = path;
CGFloat width = [UIScreen mainScreen].bounds.size.width;
CGFloat height = [UIScreen mainScreen].bounds.size.height;
self.videoHeight = height > width ? width * 0.6 : height * 0.6;
self.videoWidth = [UIScreen mainScreen].bounds.size.width-2*kLrMargin;
[self.layer addSublayer:self.playerlayer];
[self addSubview:self.toolView];
}
return self;
}
- 屏幕旋轉(zhuǎn)時做一些事
//屏幕旋轉(zhuǎn)時觸發(fā) 這里寫在父類中
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[self.videoView resetFrame:size];
}
//旋轉(zhuǎn)屏幕重設frame
- (void)resetFrame:(CGSize)size {
CGFloat width = size.width;
CGFloat height = size.height;
self.videoHeight = height > width ? width * 0.6 : height * 0.6;
self.videoWidth = size.width - 2 * kLrMargin;
if (self.isFullScreen) {
//全屏時旋轉(zhuǎn)
[self setPlayerWithPosition:CGPointZero andSize:size];
} else {
//普通旋轉(zhuǎn)
[self setPlayerWithPosition:CGPointMake(kLrMargin, kTopMargin) andSize:CGSizeMake(self.videoWidth, self.videoHeight)];
//刷新frame
[self toolView];
[self playSlider];
[self progress];
}
}
- 懶加載刷新frame
//進度懶加載 調(diào)用時只刷新frame
- (UIProgressView *)progress {
if (!_progress) {
_progress = [[UIProgressView alloc] init];
_progress.progress = 0;
}
_progress.frame = CGRectMake(2, self.playSlider.frame.size.height/2, self.playSlider.frame.size.width-2-2, kUIHeight);
return _progress;
}
AVPlayer的基本操作
基本操作包括 播放 吩坝、暫停、 停止哑蔫、 播放指定位置钉寝、緩存進度
播放網(wǎng)絡地址時 在info.plist中添加 App Transport Security Settings字典中添加Allow Arbitrary Loads元素 值為YES
使用AVPlayer播放視頻就必須用到AVPlayerlayer用來顯示播放視圖凫碌。
//加載顯示層
- (AVPlayerLayer*)playerlayer {
if (!_playerlayer) {
_playerlayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
_playerlayer.bounds = CGRectMake(0, 0, self.videoWidth, self.videoHeight);
_playerlayer.anchorPoint = CGPointMake(0, 0);
_playerlayer.position = CGPointMake(kLrMargin, kTopMargin);
_playerlayer.backgroundColor = [UIColor blackColor].CGColor;
}
return _playerlayer;
}
//加載播放類
- (AVPlayer *)player {
if (!_player) {
_player = [AVPlayer playerWithURL:[self getUrlPath:self.path]];
//kvo注冊
[self addObservers];
}
return _player;
}
- 使用KVO對狀態(tài)和緩存進行檢測享扔,添加KVO時養(yǎng)成習慣寫好移除操作
//注冊kvo
- (void)addObservers{
[self.player.currentItem addObserver:self forKeyPath:kItemStatus options:NSKeyValueObservingOptionNew context:nil];
[self.player.currentItem addObserver:self forKeyPath:kItemLoadedTimeRanges options:NSKeyValueObservingOptionNew context:nil];
}
//移除kvo
- (void)dealloc {
[self.player.currentItem removeObserver:self forKeyPath:kItemStatus];
[self.player.currentItem removeObserver:self forKeyPath:kItemLoadedTimeRanges];
}
//kvo回調(diào)
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if ([keyPath isEqualToString:kItemStatus]) {
AVPlayerItem *item = object;
if (item.status == AVPlayerItemStatusReadyToPlay) {
//準備播放
[self readyToplayWithItem:item];
}else if (item.status == AVPlayerItemStatusUnknown) {
//播放失敗
//這里寫個alertView提示下就行
}else if (item.status == AVPlayerItemStatusFailed) {
//播放失敗
//同上
}
} else if ([keyPath isEqualToString:kItemLoadedTimeRanges]) {
AVPlayerItem *item = object;
[self getLoadedTimeRanges:item];
}
}
- 基礎功能
//播放 暫停
- (void)play {
if (self.playBtn.selected) {
self.playBtn.selected = NO;
[self.player pause];
} else {
self.playBtn.selected = YES;
[self.player play];
[self timerStar];
}
}
//停止
- (void)stop {
[self.player pause];
[self.player seekToTime:CMTimeMake(0, 1)];
self.playBtn.selected = NO;
}
//全屏
- (void)fullScreen {
self.toolView.hidden = YES;
self.isFullScreen = YES;
self.backgroundColor = [UIColor blackColor];
self.playerlayer.bounds = [UIScreen mainScreen].bounds;
self.playerlayer.anchorPoint = CGPointMake(0, 0);
self.playerlayer.position = CGPointMake(0, 0);
}
//播放指定位置
- (void)playCurrentVideo {
self.playBtn.selected = YES;
NSTimeInterval second = self.playSlider.value;
[self.player.currentItem seekToTime:CMTimeMake(second,1)];
[self.player play];
[self timerStar];
}
- 具體操作
- 包括格式化時間
- 格式化路徑
- 播放準備
- 緩存計算
- 觸摸關閉全屏
- 設置video的大小位置
//設置video的frame
- (void)setPlayerWithPosition:(CGPoint)position andSize:(CGSize)size {
self.playerlayer.anchorPoint = CGPointMake(0, 0);
self.playerlayer.position = position;
self.playerlayer.bounds = CGRectMake(0, 0, size.width, size.height);
}
//準備播放
- (void)readyToplayWithItem:(AVPlayerItem*)item {
self.playBtn.enabled = YES;
long long durationSecond = item.duration.value / item.duration.timescale;
self.durationLab.text = [NSString stringWithFormat:@" / %@",[self getFormatDate:durationSecond]];
self.playSlider.maximumValue = durationSecond;
self.playSlider.minimumValue = 0;
[self.playSlider addTarget:self action:@selector(playCurrentVideo) forControlEvents:UIControlEventValueChanged];
}
//獲得緩存
- (void)getLoadedTimeRanges:(AVPlayerItem*)item {
NSValue *value = [item.loadedTimeRanges lastObject];
CMTimeRange range = [value CMTimeRangeValue];
long long cacheSecond = range.start.value/range.start.timescale + range.duration.value/range.duration.timescale;
long long currentSecond = item.currentTime.value / item.currentTime.timescale;
self.progress.progress = (currentSecond + cacheSecond) * 0.1;
}
//格式化時間
- (NSString*)getFormatDate:(NSTimeInterval)time {
int seconds = (int)time % 60;
int minutes = (int)(time / 60) % 60;
int hours = (int)time / 3600;
return [NSString stringWithFormat:@"%02d:%02d:%02d",hours,minutes,seconds];
}
//格式化url路徑
- (NSURL*)getUrlPath:(NSString*)path {
NSURL *url;
if ([self.path containsString:@"http"]) {
url = [NSURL URLWithString:self.path];
} else {
url = [NSURL fileURLWithPath:self.path];
}
return url;
}
//開啟定時
- (void)timerStar {
//定時回調(diào)
__weak typeof(self) weakSelf = self;
[self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:NULL usingBlock:^(CMTime time) {
long long current = weakSelf.player.currentItem.currentTime.value / weakSelf.player.currentItem.currentTime.timescale;
weakSelf.playSlider.value = current;
NSString *currentFormat = [weakSelf getFormatDate:current];
weakSelf.currentTimeLab.text = [NSString stringWithFormat:@"%@",currentFormat];
}];
}
//觸摸關閉全屏
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
if (self.isFullScreen) {
self.toolView.hidden = NO;
self.backgroundColor = [UIColor clearColor];
[self setPlayerWithPosition:CGPointMake(kLrMargin, kTopMargin) andSize:CGSizeMake(self.videoWidth, self.videoHeight)];
[self toolView];
[self playSlider];
[self progress];
self.isFullScreen = NO;
}
}
這樣一個簡單AVPlayer的封裝就做好了