iOS 自定义视频播放器
今天看到有许多问道有关视频播放器的问题,那么现在就来写个自定义视频播放器的 Demo 吧
#import <AVFoundation/AVFoundation.h>,#import <MediaPlayer/MediaPlayer.h>来实现的
所以,需要引用系统库文件:MediaPlayer.framework.
实现代码如下:
#import "MoviePlayerViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
@interface MoviePlayerViewController ()
@property(nonatomic,strong)AVPlayer *player; // 播放属性
@property(nonatomic,strong)AVPlayerItem *playerItem; // 播放属性
@property(nonatomic,assign)CGFloat width; // 坐标
@property(nonatomic,assign)CGFloat height; // 坐标
@property(nonatomic,strong)UISlider *slider; // 进度条
@property(nonatomic,strong)UILabel *currentTimeLabel; // 当前播放时间
@property(nonatomic,strong)UILabel *systemTimeLabel; // 系统时间
@property(nonatomic,strong)UIView *backView; // 上面一层Viewd
@property(nonatomic,assign)CGPoint startPoint;
@property(nonatomic,assign)CGFloat systemVolume;
@property(nonatomic,strong)UISlider *volumeViewSlider;
@property(nonatomic,strong)UIActivityIndicatorView *activity; // 系统菊花
@property(nonatomic,strong)UIProgressView *progress; // 缓冲条
@property(nonatomic,strong)UIView *topView;
@end
@implementation MoviePlayerViewController
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
_width = [[UIScreen mainScreen]bounds].size.height;
_height = [[UIScreen mainScreen]bounds].size.width;
// 创建AVPlayer
self.playerItem = [AVPlayerItem playerItemWithURL:[NSURL URLWithString:@"http://baobab.cdn.wandoujia.com/14468618701471.mp4"]];
self.player = [AVPlayer playerWithPlayerItem:_playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
playerLayer.frame = CGRectMake(0, 0, _width, _height);
playerLayer.videoGravity = AVLayerVideoGravityResize;
[self.view.layer addSublayer:playerLayer];
[_player play];
//AVPlayer播放完成通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem];
self.backView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, _width, _height)];
[self.view addSubview:_backView];
_backView.backgroundColor = [UIColor clearColor];
self.topView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, _width, _height * 0.15)];
_topView.backgroundColor = [UIColor blackColor];
_topView.alpha = 0.5;
[_backView addSubview:_topView];
[self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];// 监听loadedTimeRanges属性
[self createProgress];
[self createSlider];
[self createCurrentTimeLabel];
[self createButton];
[self backButton];
[self createTitle];
[self createGesture];
[self customVideoSlider];
self.activity = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
_activity.center = _backView.center;
[self.view addSubview:_activity];
[_activity startAnimating];
// //延迟线程
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.5 animations:^{
_backView.alpha = 0;
}];
});
//计时器
[NSTimer scheduledTimerWithTimeInterval:1.f target:self selector:@selector(Stack) userInfo:nil repeats:YES];
// self.modalPresentationCapturesStatusBarAppearance = YES;
}
#pragma mark - 横屏代码
- (BOOL)shouldAutorotate{
return NO;
} //NS_AVAILABLE_IOS(6_0);当前viewcontroller是否支持转屏
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
} //当前viewcontroller支持哪些转屏方向
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight;
}
- (BOOL)prefersStatusBarHidden
{
return NO; // 返回NO表示要显示,返回YES将hiden
}
#pragma mark - 创建UISlider
- (void)createSlider
{
self.slider = [[UISlider alloc]initWithFrame:CGRectMake(100, 345, _width * 0.7, 15)];
[self.backView addSubview:_slider];
[_slider setThumbImage:[UIImage imageNamed:@"iconfont-yuan.png"] forState:UIControlStateNormal];
[_slider addTarget:self action:@selector(progressSlider:) forControlEvents:UIControlEventValueChanged];
_slider.minimumTrackTintColor = [UIColor colorWithRed:30 / 255.0 green:80 / 255.0 blue:100 / 255.0 alpha:1];
}
#pragma mark - slider滑动事件
- (void)progressSlider:(UISlider *)slider
{
//拖动改变视频播放进度
if (_player.status == AVPlayerStatusReadyToPlay) {
// //计算出拖动的当前秒数
CGFloat total = (CGFloat)_playerItem.duration.value / _playerItem.duration.timescale;
// NSLog(@"%f", total);
NSInteger dragedSeconds = floorf(total * slider.value);
// NSLog(@"dragedSeconds:%ld",dragedSeconds);
//转换成CMTime才能给player来控制播放进度
CMTime dragedCMTime = CMTimeMake(dragedSeconds, 1);
[_player pause];
[_player seekToTime:dragedCMTime completionHandler:^(BOOL finish){
[_player play];
}];
}
}
#pragma mark - 创建UIProgressView
- (void)createProgress
{
self.progress = [[UIProgressView alloc]initWithFrame:CGRectMake(102, 352, _width * 0.69, 15)];
[_backView addSubview:_progress];
}
#pragma mark -
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
NSTimeInterval timeInterval = [self availableDuration];// 计算缓冲进度
// NSLog(@"Time Interval:%f",timeInterval);
CMTime duration = self.playerItem.duration;
CGFloat totalDuration = CMTimeGetSeconds(duration);
[self.progress setProgress:timeInterval / totalDuration animated:NO];
}
}
- (NSTimeInterval)availableDuration {
NSArray *loadedTimeRanges = [[_player currentItem] loadedTimeRanges];
CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 获取缓冲区域
float startSeconds = CMTimeGetSeconds(timeRange.start);
float durationSeconds = CMTimeGetSeconds(timeRange.duration);
NSTimeInterval result = startSeconds + durationSeconds;// 计算缓冲总进度
return result;
}
- (void)customVideoSlider {
UIGraphicsBeginImageContextWithOptions((CGSize){ 1, 1 }, NO, 0.0f);
UIImage *transparentImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// [self.slider setMinimumTrackImage:transparentImage forState:UIControlStateNormal];
[self.slider setMaximumTrackImage:transparentImage forState:UIControlStateNormal];
}
#pragma mark - 创建播放时间
- (void)createCurrentTimeLabel
{
self.currentTimeLabel = [[UILabel alloc]initWithFrame:CGRectMake(_width *0.86, 342, 100, 20)];
[self.backView addSubview:_currentTimeLabel];
_currentTimeLabel.textColor = [UIColor whiteColor];
// _currentTimeLabel.backgroundColor = [UIColor blueColor];
_currentTimeLabel.font = [UIFont systemFontOfSize:12];
_currentTimeLabel.text = @"00:00/00:00";
}
#pragma mark - 计时器事件
- (void)Stack
{
if (_playerItem.duration.timescale != 0) {
_slider.maximumValue = 1;//音乐总共时长
_slider.value = CMTimeGetSeconds([_playerItem currentTime]) / (_playerItem.duration.value / _playerItem.duration.timescale);//当前进度
//当前时长进度progress
NSInteger proMin = (NSInteger)CMTimeGetSeconds([_player currentTime]) / 60;//当前秒
NSInteger proSec = (NSInteger)CMTimeGetSeconds([_player currentTime]) % 60;//当前分钟
// NSLog(@"%d",_playerItem.duration.timescale);
// NSLog(@"%lld",_playerItem.duration.value/1000 / 60);
//duration 总时长
NSInteger durMin = (NSInteger)_playerItem.duration.value / _playerItem.duration.timescale / 60;//总秒
NSInteger durSec = (NSInteger)_playerItem.duration.value / _playerItem.duration.timescale % 60;//总分钟
self.currentTimeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld / %02ld:%02ld", proMin, proSec, durMin, durSec];
}
if (_player.status == AVPlayerStatusReadyToPlay) {
[_activity stopAnimating];
} else {
[_activity startAnimating];
}
}
#pragma mark - 播放和下一首按钮
- (void)createButton
{
UIButton *startButton = [UIButton buttonWithType:UIButtonTypeCustom];
startButton.frame = CGRectMake(15, 337, 30, 30);
[self.backView addSubview:startButton];
if (_player.rate == 1.0) {
[startButton setBackgroundImage:[UIImage imageNamed:@"pauseBtn@2x.png"] forState:UIControlStateNormal];
} else {
[startButton setBackgroundImage:[UIImage imageNamed:@"playBtn@2x.png"] forState:UIControlStateNormal];
}
[startButton addTarget:self action:@selector(startAction:) forControlEvents:UIControlEventTouchUpInside];
UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeCustom];
nextButton.frame = CGRectMake(60, 340, 25, 25);
[self.backView addSubview:nextButton];
[nextButton setBackgroundImage:[UIImage imageNamed:@"nextPlayer@3x.png"] forState:UIControlStateNormal];
}
#pragma mark - 播放暂停按钮方法
- (void)startAction:(UIButton *)button
{
if (button.selected) {
[_player play];
[button setBackgroundImage:[UIImage imageNamed:@"pauseBtn@2x.png"] forState:UIControlStateNormal];
} else {
[_player pause];
[button setBackgroundImage:[UIImage imageNamed:@"playBtn@2x.png"] forState:UIControlStateNormal];
}
button.selected =!button.selected;
}
#pragma mark - 返回按钮方法
- (void)backButton
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(15, 20, 30, 30);
[button setBackgroundImage:[UIImage imageNamed:@"iconfont-back.png"] forState:UIControlStateNormal];
[_topView addSubview:button];
[button addTarget:self action:@selector(backButtonAction) forControlEvents:UIControlEventTouchUpInside];
}
#pragma mark - 创建标题
- (void)createTitle
{
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(80, 20, 250, 30)];
[_backView addSubview:label];
label.textColor = [UIColor whiteColor];
label.textAlignment = NSTextAlignmentCenter;
}
#pragma mark - 创建手势
- (void)createGesture
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapAction:)];
[self.view addGestureRecognizer:tap];
//获取系统音量
MPVolumeView *volumeView = [[MPVolumeView alloc] init];
_volumeViewSlider = nil;
for (UIView *view in [volumeView subviews]){
if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
_volumeViewSlider = (UISlider *)view;
break;
}
}
_systemVolume = _volumeViewSlider.value;
}
#pragma mark - 轻拍方法
- (void)tapAction:(UITapGestureRecognizer *)tap
{
if (_backView.alpha == 1) {
[UIView animateWithDuration:0.5 animations:^{
_backView.alpha = 0;
}];
} else if (_backView.alpha == 0){
[UIView animateWithDuration:0.5 animations:^{
_backView.alpha = 1;
}];
}
if (_backView.alpha == 1) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(7 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.5 animations:^{
_backView.alpha = 0;
}];
});
}
}
#pragma mark - 滑动调整音量大小
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
if(event.allTouches.count == 1){
//保存当前触摸的位置
CGPoint point = [[touches anyObject] locationInView:self.view];
_startPoint = point;
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if(event.allTouches.count == 1){
//计算位移
CGPoint point = [[touches anyObject] locationInView:self.view];
// float dx = point.x - startPoint.x;
float dy = point.y - _startPoint.y;
int index = (int)dy;
if(index>0){
if(index%5==0){//每10个像素声音减一格
NSLog(@"%.2f",_systemVolume);
if(_systemVolume>0.1){
_systemVolume = _systemVolume-0.05;
[_volumeViewSlider setValue:_systemVolume animated:YES];
[_volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
}else{
if(index%5==0){//每10个像素声音增加一格
NSLog(@"+x ==%d",index);
NSLog(@"%.2f",_systemVolume);
if(_systemVolume>=0 && _systemVolume<1){
_systemVolume = _systemVolume+0.05;
[_volumeViewSlider setValue:_systemVolume animated:YES];
[_volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
}
//亮度调节
// [UIScreen mainScreen].brightness = (float) dx/self.view.bounds.size.width;
}
}
- (void)moviePlayDidEnd:(id)sender
{
// [_player pause];
[self dismissViewControllerAnimated:YES completion:^{
}];
}
- (void)backButtonAction
{
[_player pause];
[self dismissViewControllerAnimated:YES completion:^{
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
iOS 自定义视频播放器相关推荐
- Android进阶:自定义视频播放器开发(下)
上一篇文章我们主要讲了视频播放器开发之前需要准备的一个知识,TextureView,用于对图像流的处理.这篇文章开始构建一个基础的视频播放器. 一.准备工作 在之前的文章已经说过了,播放器也是一个vi ...
- iOS AVPlayer视频播放器
代码地址如下: http://www.demodashi.com/demo/11168.html 一.运行效果 二.实现过程 ①.创建播放器avPlayer //创建播放器url = [url str ...
- Android开发笔记(一百二十五)自定义视频播放器
视频播放方式 在Android中播放视频的方式有两种: 1.使用MediaPlayer结合SurfaceView进行播放.其中通过SurfaceView显示视频的画面,通过MediaPlayer来设置 ...
- 一步步自定义视频播放器——TextureView+MediaPlayer自定义视频播放器
本篇参考封装一个视频播放器,原文已经写的非常棒了,本篇加入了个人对其内容的理解.秉承不重复造轮子的良好理念,接下来开始拆解轮子.内容非常多,我都差点放弃写,有耐心的请往下看 github上非常棒的视频 ...
- Android自定义视频播放器(三)
参看:Android自定义视频播放器(一):https://blog.csdn.net/zxd1435513775/article/details/81507909 参看:Android自定义视频播放 ...
- HTML5 自定义视频播放器
HTML5 自定义视频播放器 第一步:获取播放器 第二步:实现播放与暂停 第三步:实现全屏操作 第四步:实现播放的逻辑 第五步:实现播放过程的逻辑 第六步:实现视频的跳播 第七步:播放完毕后重置播放器 ...
- 自定义视频播放器与慢放滚轮
受同学之邀,帮忙自定义一控件.需求是:开发慢放滚轮,用手指拨动实现帧级的慢速播放,滚轮可双向拨动,其滚动具有惯性,滚动速度决定视频播放的速度.需求很明朗,可我却是一头雾水.说实话,在此之前我还没有自定 ...
- Android 自定义视频播放器
由于录像之后,原先选用的腾讯VOD点播播放器显示出来竖屏都变横屏了,虽然选中了现在的腾讯VOD点播,还是把Android视频播放器了解了一番. Android自定义视频播放器有以下三种: 一.Medi ...
- HTML5视频(自定义视频播放器源码)
video对象 兼容情况: safari浏览器不支持webm格式 Chrome浏览器支持webm格式 ie8以及以下不支持video标签 , ie9支持video标签 ,但是支持mp4格式的 Fire ...
- Android进阶:自定义视频播放器开发(上)
随着快手,抖音,西瓜视频等视频APP的崛起,视频播放已经成为主流,此时作为Android研发的你,想要提高自己的能力还不知道怎么开发视频播放器怎么行?所以今天就带着大家一起开发一个简易播放器:Smal ...
最新文章
- 制度汇编格式怎么生成目录_来自世界500强企业的管理表格DOC格式 1900套
- 最新调查:等这一波COBOL程序员退休,很多关键岗位就后继无人了
- GitHub最最最火的开源爬虫工具箱,一爬就取
- java object 引用类型_java中的四种引用类型
- arduino代码_arduino智能小车项目——01、配件介绍及代码部分教程
- java设计智慧教室_物联网智慧教室设计方案,更便捷的智慧教学体验
- Bootstrap 异常
- 获取当前电脑全部网络连接名字
- 构建插件式的应用程序框架(四)----服务容器(ZT)
- awk 字符串替换 gsub
- IDEA maven库里 添加自定义jar包
- stdafx.h到底有什么用
- 搭建公司wiki系统
- 从游戏中学习产品设计04:成就篇
- 戴尔服务器关闭系统自检,戴尔开机自检取消操作方法
- 手机,电脑都能用的,整人,恶搞代码连接,“你不会百度一下吗”教你用百度
- asp.net 面试题目
- 针对此次疫情的防控建议
- C语言简单入门教程(初学者用)
- vrp量子遗传matlab,遗传算法求解VRP问题的技术报告
热门文章
- Structs2-基础
- 我的世界手机版javaui材质包_传奇世界有元神怀旧版下载-传奇世界有元神怀旧版手机下载v1.0...
- Resource Hacker软件更换应用图标
- 回归方程的拟合优度检验_回归分析的“拟合优度”是什么?
- HSqlDB认识及使用
- 软件测试工程师企业级培训视频教程
- ArcGIS分享: 地图分幅及编号
- 新买的笔记本电脑怎么分盘_2020年笔记本电脑选购有哪些建议和推荐?
- 元宇宙8大创业方向:虚拟偶像、数字孪生…
- 简单易用的标签列表界面(宝宝用了都不哭了 )