VLC集成与使用

来源:互联网 发布:柯哀分析文 知乎 编辑:程序博客网 时间:2024/06/05 09:10

VLC的集成和使用
VLC介绍
VLC Media Player (VideoLAN) 为 Windows、Linux、OS X、Android、iOS、Windows Phone等平台提供一个视频播放器、解码器。它可以播放来自网络、摄像头、磁盘、光驱的文件,支持包括MPEG 1/2/4, H264, VC-1, DivX, WMV, Vorbis, AC3, AAC等格式的解码。在 Windows 和 Linux 上的 VLC 是使用C++/Qt写成,提供了一致的用户体验。同时 VLC 还专门为 OS X 提供了原生版本,OS X 版的 VLC 的用户界面使用Cocoa框架编写,在 OS X 下拥有卓越的原生体验。

VLC还有一个非常好的功能——播放那些没有下载完整的视频文件。
VLC几乎覆盖所有媒体格式。
VLC集成
在iOS下,我们可以很方便的使用VLC,因为它经行了优秀的封装,源码中最核心的部分被封装成了独立的库(MoblieVLVKit.framework库),它是基于FFmpeg,Live555提供完整的媒体播放库,所以整一个库体积还是比较大(目前已经超过600M了),不过并不会太影响App的大小,经行App打包发布的是会自动超级压缩的。经过测试它比使用FFmpeg库仅仅是多7M左右的大小。
VLC cocoapods方式集成

VLC可以有多种的方式安装,目前最简单的方式就是cocoapods安装,以前需要下载源码后经行编译,编译后的还分模拟器版和真机版,最后还得使用lipo 命令经行合并,比较麻烦,这里我就不进行介绍了,因为没必要(喜欢折腾的可以自行搜索相关资料),最终编译得到的结果一样是MoblieVLCKit.framework库,即使项目不允许使用cocoapods,也可以建立空项目后使用cocoapods得到MoblieVLCKit.framework在经行移植。

步骤

1.在podfile中写入:pod 'MobileVLCKit'2.终端执行pod install即可(成功后会在项目里看到MoblieVLCKit.framework库)3.添加依赖库:libz.tbd、libbz2.tbd、libiconv.tbd、libstdc++.6.0.9.tbd

VLC使用
MoblieVLCKit为我们提供了很多功能接口,不过我们不需要全部了解,只需要懂得几个常用的API接口就可以轻轻松松的写出一个播放器出来。因为它支持定制化UI,所以有心的开发者可以结合漂亮的UI设计一套专属的播放器
MoblieVLCKit 常用API介绍
VLCMediaPlayer

VCL对象,管理着播放的开始暂停等操作,有着几个代理方法可以经行状态和时间的监听回调

VLCMediaPlayer属性

// 播放设置,比如设置播放路径是本地播放还是网络播放,以及播放的画面映射到哪个View@property (NS_NONATOMIC_IOSONLY, strong) VLCMedia *media;

VLCMediaPlayer方法

// 开始播放-(BOOL)play;// 暂停播放- (void)pause;// 停止播放- (void)stop;/**  *快进播放  *interval:需要快进的秒数*/- (void)jumpForward:(int)interval;/**  *快退播放  *interval:需要快退的秒数*/- (void)jumpBackward:(int)interval;// 短时间的快退(10秒)- (void)shortJumpBackward;// 短时间的快进(10秒)- (void)shortJumpForward;/**  * 以一定倍速播放  * rate:倍速*/- (void)fastForwardAtRate:(float)rate;

VLCMediaPlayer代理

// 播放状态改变的回调- (void)mediaPlayerStateChanged:(NSNotification *)aNotification;// 播放时间改变的回调- (void)mediaPlayerTimeChanged:(NSNotification *)aNotification;

效果图这里写图片描述

VLCPlayer.h和VLCPlayer.m(VLC创建)

  ////  VLCPlayer.h//  VLCDemo////  Created by pocket on 16/6/27.//  Copyright © 2016年 pocket. All rights reserved.//// VLC播放对象#import <Foundation/Foundation.h>#import <MobileVLCKit/MobileVLCKit.h>#import <UIKit/UIKit.h>@interface VLCPlayer : NSObject/** *  VCL对象 */@property (nonatomic, strong) VLCMediaPlayer *player;/** *  根据路径初始化VCL对象 * *  @param playView 播放承载View *  @param path     本地路径 * *  @return VLCPlayer 类 */- (id)initWithView:(UIView *)playView andMediaPath:(NSString *)path;/** *  根据URL初始化VCL对象 * *  @param playView 播放承载View *  @param url      url路径 * *  @return VLCPlayer 类 */- (id)initWithView:(UIView *)playView andMediaURL:(NSURL *)url;/** *  开始播放 */- (void)playMedia;/** *  暂停播放 */- (void)stopPlaying;@end
    ////  VLCPlayer.m//  VLCDemo////  Created by pocket on 16/6/27.//  Copyright © 2016年 pocket. All rights reserved.//#import "VLCPlayer.h"@implementation VLCPlayer- (id)initWithView:(UIView *)playView andMediaPath:(NSString *)path {    self = [super init];    if (self) {        // 创建VCL对象        _player = [[VLCMediaPlayer alloc] init];        // 设置VCL播放界面的View        _player.drawable = playView;        // 设置需要加载的路径        VLCMedia *media = [VLCMedia mediaWithPath:path];        [_player setMedia:media];    }    return self;}- (id)initWithView:(UIView *)playView andMediaURL:(NSURL *)url {    self = [super init];    if (self) {        _player = [[VLCMediaPlayer alloc] init];        _player.drawable = playView;        // 设置需要加载的url        VLCMedia *media = [VLCMedia mediaWithURL:url];        [_player setMedia:media];    }    return self;}// 播放- (void)playMedia {    [_player play];}// 暂停- (void)stopPlaying {    [_player stop];}@end

VLCViewController.h/VLCViewController.m(播放控制器)

//  VLCViewController.h//  VLCDemo////  Created by pocket on 16/6/27.//  Copyright © 2016年 pocket. All rights reserved.//// VLC播放控制器#import <UIKit/UIKit.h>#import "VLCPlayer.h"@interface VLCViewController : UIViewController/** *  文件名字 */@property (nonatomic, strong) NSString *playName;/** *  文件路径(本地资源路径) */@property (nonatomic, strong) NSString *playPath;/** *  网络URL路径 */@property (nonatomic, strong) NSURL *playURL;@property (nonatomic, strong) VLCPlayer *player;@end
//  VLCViewController.m//  VLCDemo////  Created by pocket on 16/6/27.//  Copyright © 2016年 pocket. All rights reserved.//#import "VLCViewController.h"#import <AVFoundation/AVFoundation.h>#import<MobileVLCKit/MobileVLCKit.h>#import "VLCPlayerView.h"@interface VLCViewController ()<VLCMediaPlayerDelegate>/** *  VLC承载视图 */@property (nonatomic,strong) VLCPlayerView *vlcPlayerView;/** *  是否本地路径 */@property (nonatomic,assign) BOOL isLocal;/** *  视频总时间(秒) */@property (nonatomic,assign) int videoAllTime;/** *  当前播放时间(秒) */@property (nonatomic,assign) int videoCurrentTime;/** *  当前进度 */@property (nonatomic,assign) float currentProgress;/** *  菊花加载 */@property (nonatomic,strong) UIActivityIndicatorView *activityView;@end@implementation VLCViewController- (void)viewDidLoad {  [super viewDidLoad];  self.title = self.playName;  self.videoAllTime = 0;  [self tarnsformView];  // 添加播放的承载View  [self addVLCPalyerView];  // 菊花  self.activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];  self.activityView.center = self.vlcPlayerView.center;  [self.activityView setHidesWhenStopped:YES]; // 旋转时隐藏  [self.activityView startAnimating]; // 开始旋转  [self.view addSubview:self.activityView];  //视频播放  if (_playPath) { // 本地      _player = [[VLCPlayer alloc] initWithView:self.vlcPlayerView.playView andMediaPath:_playPath];      _player.player.delegate = self;      [_player playMedia]; // 播放      self.isLocal = YES;  }  if (_playURL) { // 网络      _player = [[VLCPlayer alloc] initWithView:self.vlcPlayerView.playView andMediaURL:_playURL];      _player.player.delegate = self;      [_player playMedia];      self.isLocal = NO;  }}- (void)dealloc{    [_player stopPlaying];    _player = nil;}+ (void)initialize{    AVAudioSession *session = [AVAudioSession sharedInstance];    [session setCategory:AVAudioSessionCategoryPlayback error:nil];    [session setActive:YES error:nil];}- (void)viewDidAppear:(BOOL)animated {    [super viewDidAppear:animated];    [self addObserver];}- (void)viewDidDisappear:(BOOL)animated {    [super viewDidDisappear:animated];    [self removeObserver];}#pragma mark - -- 屏幕旋转控制处理// 这里采用假旋转,因为其他界面并不需要支持横屏(缺点是状态栏不支持转动,所以采取presentView方式最好)- (void)tarnsformView{    // 旋转view    self.view.transform = CGAffineTransformMakeRotation(M_PI/2); // 旋转90°    CGRect frame = [UIScreen mainScreen].applicationFrame; // 获取当前屏幕大小    // 重新设置所有view的frame    self.view.bounds = CGRectMake(0, 0,frame.size.height + 20,frame.size.width);    self.vlcPlayerView.frame = self.view.bounds;}// 隐藏状态栏显得和谐- (BOOL)prefersStatusBarHidden{    return YES;}#pragma mark - -- 播放的承载View的设置- (void)addVLCPalyerView{    //承载播放的视图初始化(自定义播放界面可在这里做UI定制)    self.vlcPlayerView = [[VLCPlayerView alloc] initWithFrame:self.view.bounds];    // 设置视频名称    self.vlcPlayerView.videoName = self.playName;    // 设置播放监听回调    __weak typeof(self) weakSelf = self;    self.vlcPlayerView.playBlock = ^(UIButton *playBtn){        [weakSelf playClick:playBtn];    };    // 设置进度条监听回调    self.vlcPlayerView.changeSliderBlock = ^(UISlider *sliderView){        [weakSelf changeProgress:sliderView];    };    // 设置屏幕锁监听回调    self.vlcPlayerView.lockBlock = ^(UIButton *lockBtn){        // 屏幕锁操作逻辑        // ...后续    };    // 设置返回按钮回调    self.vlcPlayerView.backBlock = ^{        // 关闭视图控制器        [weakSelf.player stopPlaying];        [weakSelf dismissViewControllerAnimated:YES completion:^{        }];    };    // 左右滑动手势结束回调    self.vlcPlayerView.endPanGesture = ^(float progress,int type){        if (type == 4) { // 快退            [weakSelf.player.player shortJumpBackward];        } else if (type == 3) { // 快进            [weakSelf.player.player shortJumpForward];        }    };    [self.view addSubview:self.vlcPlayerView];}    #pragma mark - -- vlcPlayerView播放操作// 播放(暂停)监听- (void)playClick:(UIButton *)playBtn{    if ([_player.player isPlaying]) { // 正在播放        [_player.player pause]; // 暂停    } else {        [_player.player play]; // 播放    }}// 倍率速度播放(一般很少使用)- (void)fastForwardAtRate:(float)rate{    [_player.player fastForwardAtRate:rate];}// 进度条拖拽- (void)changeProgress:(UISlider *)sliderView{    if (!_player.player.isPlaying) { // 防止暂停状态拖动(拖动触发播放)        [self.vlcPlayerView changePlayBtnState:YES];        [_player.player play];    }    // 根据拖动比例计算开始到播放节点的总秒数    int allSec = (int)(self.videoAllTime * sliderView.value);    // 根据当前播放秒数计算需要seek的秒数    int sec = abs(allSec - self.videoCurrentTime);    // 如果为获取到时间信息    if (sec == 0 && allSec == 0) {        [[AlertViewManager shareInstance] showPromptText:self.view context:CustomLocalizedString(@"未获取到视频总时间,请尝试手势快进", nil) minSize:CGSizeMake(60,44) afterDelay:2.0];        return;    }    NSLog(@"sec:%d",sec);    if (sec==0) { // 刚好等于视频总时间        [_player.player stop];        return;    }    if (self.currentProgress<=sliderView.value) { // 快进滑动        [_player.player jumpForward:sec]; // 快进播放    } else {        [_player.player jumpBackward:sec]; // 快退播放    }}#pragma  mark - -- vlcPlayerView时间和进度刷新- (void)updateTime{    // 设置剩余时间    self.vlcPlayerView.remainingTime = [[_player.player remainingTime] stringValue];    // 设置当前时间    self.vlcPlayerView.currentTime = [[_player.player time] stringValue];    // 设置当前进度    self.vlcPlayerView.sliderValue = [_player.player position];}#pragma mark - -- KVO监听// 添加监听- (void)addObserver{    // 监听VLC对象属性(时间和播放)    [_player.player addObserver:self forKeyPath:@"remainingTime" options:0 context:nil];    [_player.player addObserver:self forKeyPath:@"isPlaying" options:0 context:nil];}// 移除监听- (void)removeObserver{    [_player.player removeObserver:self forKeyPath:@"remainingTime"];    [_player.player removeObserver:self forKeyPath:@"isPlaying"];}// kvo监听回调- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {    // 可以在这里设置显示的时间和进度    // position:VLCMediaPlayer对象中的进度比例,可用此值设置播放进度//    NSLog(@"[_player.player position]:%lf",[_player.player position]);    // remainingTime:VLCMediaPlayer对象中的剩余时间,stringValue可以转化为时间格式字符串//    NSLog(@"[[_player.player remainingTime] stringValue]:%@",[[_player.player remainingTime] stringValue]);    // time:VLCMediaPlayer对象中的当前时间//    NSLog(@"[[_player.player time] stringValue]:%@", [[_player.player time] stringValue]);//    NSLog(@"剩余的分钟:%@",[[_player.player remainingTime] minuteStringValue]);//    NSLog(@"播放的分钟:%@",[[_player.player time] minuteStringValue]);    // 记录当前进度    self.currentProgress = [_player.player position];    // 根据分钟计算播放的秒数(这里不够严格,还得加上秒数)    self.videoCurrentTime = [[[_player.player time] minuteStringValue] intValue] * 60;    // 根据剩余时间和已经播放的计算总秒数(这里不够严格,还得加上秒数)    self.videoAllTime = [[[_player.player remainingTime] minuteStringValue] intValue]*60 + self.videoCurrentTime;    // 有时候获取不到时间(个人想法是结合定时器和进度比例计算总时间等)    // ...    // 刷新最新时间和播放进度    [self updateTime];    // 停止菊花加载    if (self.activityView.isAnimating) {        [self.activityView stopAnimating];    }}#pragma mark - 监听程序进入前台和后台#pragma mark - VLCMediaPlayerDelegate// 播放状态改变的回调- (void)mediaPlayerStateChanged:(NSNotification *)aNotification{    /**     *  VLCMediaPlayerStateStopped,        //< Player has stopped     VLCMediaPlayerStateOpening,        //< Stream is opening     VLCMediaPlayerStateBuffering,      //< Stream is buffering     VLCMediaPlayerStateEnded,          //< Stream has ended     VLCMediaPlayerStateError,          //< Player has generated an error     VLCMediaPlayerStatePlaying,        //< Stream is playing     VLCMediaPlayerStatePaused          //< Stream is paused     */    NSLog(@"mediaPlayerStateChanged");    NSLog(@"状态:%ld",(long)_player.player.state);    switch ((int)_player.player.state) {        case VLCMediaPlayerStateStopped: // 停止播放(播放完毕或手动stop)        {            [_player.player stop]; // 手动调用一次停止(一遍再次点击播放)            [self.vlcPlayerView changePlayBtnState:NO];            if (self.activityView.isAnimating) {                [self.activityView stopAnimating];            }        }            break;        case VLCMediaPlayerStateBuffering: // 播放中缓冲状态        {            // 显示菊花            if (!self.activityView.isAnimating) {                [self.activityView startAnimating];            }        }            break;        case VLCMediaPlayerStatePlaying: // 被暂停后开始播放        {            if (self.activityView.isAnimating) {                [self.activityView stopAnimating];            }        }            break;        case VLCMediaPlayerStatePaused:  // 播放后被暂停        {            if (self.activityView.isAnimating) {                [self.activityView stopAnimating];            }        }            break;    }}// 播放时间改变的回调- (void)mediaPlayerTimeChanged:(NSNotification *)aNotification{//    NSLog(@"mediaPlayerTimeChanged");}@end

VLCPlayerView.h/VLCPlayerView.m(播放View设计)

////  VLCPlayerView.h//  VLCDemo////  Created by pocket on 16/6/28.//  Copyright © 2016年 pocket. All rights reserved.//// VLC播放界面#import <UIKit/UIKit.h>@interface VLCPlayerView : UIView/** *  承载视频的View */@property (nonatomic,strong) UIView *playView;/** *  视频名称 */@property (nonatomic,copy) NSString *videoName;/** *  剩余时间 */@property (nonatomic,copy) NSString *remainingTime;/** *  当前时间 */@property (nonatomic,copy) NSString *currentTime;/** *  当前进度 */@property (nonatomic,assign) float sliderValue;/** *  返回按钮监听回调 */@property (nonatomic,copy) void (^backBlock)(void);/** *  屏幕锁监听回调 */@property (nonatomic,copy) void (^lockBlock)(UIButton *lockBtn);/** *  播放(暂停)监听回调 */@property (nonatomic,copy) void (^playBlock)(UIButton *playBtn);/** *  进度条监听回调 */@property (nonatomic,copy) void (^changeSliderBlock)(UISlider *sliderView);/** *  拖动结束监听(progress:幅度,type: 3:右 ,4:左) */@property (nonatomic,copy) void (^endPanGesture)(float progress,int type);/** *  变更播放(暂停)按钮状态 */- (void)changePlayBtnState:(BOOL)select;@end
////  VLCPlayerView.m//  VLCDemo////  Created by pocket on 16/6/28.//  Copyright © 2016年 pocket. All rights reserved.//#import "VLCPlayerView.h"#import "CustomSlider.h"#define titleFontSize 15.0#define titleColor [UIColor whiteColor]#define backgroundViewColor RGB(0, 0, 0, 0.6)#define space 15.0#define alphaDef 0.5#define viewHeight 60.0#define gestureMinimumTranslation 20.0// 定义滑动手势类型typedef enum {    PlayerMoveDirectionNone = 0,    PlayerMoveDirectionUp,    PlayerMoveDirectionDown,    PlayerMoveDirectionRight,    PlayerMoveDirectionLeft}PlayerMoveDirection;@interface VLCPlayerView()/*********************顶部栏*************************************/@property (nonatomic,strong) UIView *topView; // 顶部view@property (nonatomic,strong) UIButton *backBtn; // 返回按钮@property (nonatomic,strong) UILabel *nameLabel; // 名字/*********************底部栏*************************************/@property (nonatomic,strong) UIView *bottomView;// 底部View// 开始播放(暂停)按钮@property (nonatomic,strong) UIButton *playBtn;@property (nonatomic,strong) CustomSlider *sliderView; // 滑动条// 当前时间标签@property (nonatomic,strong) UILabel *currentTimeLabel;// 结束时间标签@property (nonatomic,strong) UILabel *endTimeLabel;/*********************快进/快退显示********************************/@property (nonatomic,strong) UIView *baseView;// 快进/快退底View@property (nonatomic,strong) UIButton *changeBtn;@property (nonatomic,strong) UILabel *progressTitle;@property (nonatomic,strong) UIProgressView *progressView;// 屏幕锁@property (nonatomic,strong) UIButton *lockBtn;// sliderView是否正在滑动@property (nonatomic,assign) BOOL isSliding;// 滑动手势类型@property (nonatomic,assign) PlayerMoveDirection moveDirection;// 开始拖动的位置@property (nonatomic,assign) CGPoint beginPoint;// 当前拖动的位置@property (nonatomic,assign) CGPoint currentPoint;@end@implementation VLCPlayerView- (instancetype)initWithFrame:(CGRect)frame{    if (self = [super initWithFrame:frame]) {        [self setUI];        // 添加手势        [self addGesture];        // 5秒后自动隐藏        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{            if (self.topView.alpha>0.0) {                [self oneGestureClick];            }        });    }    return self;}- (void)setUI{    // 承载视频view    self.playView = [[UIView alloc] init];    self.playView.backgroundColor = [UIColor blackColor];    [self addSubview:self.playView];    // 顶部View    self.topView = [[UIView alloc] init];    self.topView.backgroundColor = backgroundViewColor;    [self addSubview:self.topView];    // 名字    self.nameLabel = [[UILabel alloc] init];    self.nameLabel.textColor = titleColor;    self.nameLabel.textAlignment = NSTextAlignmentCenter;    self.nameLabel.font = [UIFont systemFontOfSize:titleFontSize];    [self.topView addSubview:self.nameLabel];    // 返回按钮    self.backBtn = [UIButton buttonWithType:UIButtonTypeCustom];    [self.backBtn setImage:[UIImage imageNamed:@"ic_jt_bf"] forState:UIControlStateNormal];    [self.backBtn addTarget:self action:@selector(backClick) forControlEvents:UIControlEventTouchUpInside];    [self.topView addSubview:self.backBtn];    // 底部view    self.bottomView = [[UIView alloc] init];    self.bottomView.backgroundColor = backgroundViewColor;    [self addSubview:self.bottomView];    // 暂停    self.playBtn = [UIButton buttonWithType:UIButtonTypeCustom];    self.playBtn.selected = YES;    [self.playBtn setImage:[UIImage imageNamed:@"ic_bf_zt"] forState:UIControlStateSelected];    [self.playBtn setImage:[UIImage imageNamed:@"ic_bf_zt"] forState:UIControlStateNormal];    [self.playBtn setAdjustsImageWhenHighlighted:NO]; // 设置无高亮状态    [self.playBtn addTarget:self action:@selector(playBtnClick) forControlEvents:UIControlEventTouchUpInside];    [self.bottomView addSubview:self.playBtn];    // 当前标签    self.currentTimeLabel = [[UILabel alloc] init];    self.currentTimeLabel.textColor = titleColor;    self.currentTimeLabel.text = @"--:--";    self.currentTimeLabel.textAlignment = NSTextAlignmentLeft;    self.currentTimeLabel.font = [UIFont systemFontOfSize:titleFontSize];    [self.bottomView addSubview:self.currentTimeLabel];    // 结束标签    self.endTimeLabel = [[UILabel alloc] init];    self.endTimeLabel.textColor = titleColor;    self.endTimeLabel.text = @"--:--";    self.endTimeLabel.textAlignment = NSTextAlignmentRight;    self.endTimeLabel.font = [UIFont systemFontOfSize:titleFontSize];    [self.bottomView addSubview:self.endTimeLabel];    // 滑动条    self.sliderView = [[CustomSlider alloc] init];    self.sliderView.minimumTrackTintColor = TedcallStorageProgressColor; // 设置滑动过的颜色    self.sliderView.maximumTrackTintColor = [UIColor grayColor]; // 设置总长度颜色    self.sliderView.thumbTintColor = RGB(255, 255, 255, 0.7); // 设置滑块颜色    [self.sliderView addTarget:self action:@selector(slideringListening) forControlEvents:UIControlEventValueChanged];    [self.sliderView addTarget:self action:@selector(sliderChange) forControlEvents:UIControlEventTouchUpInside];    [self.bottomView addSubview:self.sliderView];    // 快进/快退view    self.baseView = [[UIView alloc] init];    self.baseView.backgroundColor = backgroundViewColor;    self.baseView.layer.cornerRadius = 8.0;    self.baseView.layer.masksToBounds = YES;    self.baseView.alpha = 0.0;    [self addSubview:self.baseView];    self.changeBtn = [UIButton buttonWithType:UIButtonTypeCustom];    [self.changeBtn setImage:[UIImage imageNamed:@"ic_kj_bf"] forState:UIControlStateNormal];    [self.changeBtn setImage:[UIImage imageNamed:@"ic_kt_bf"] forState:UIControlStateSelected];    [self.baseView addSubview:self.changeBtn];    self.progressTitle = [[UILabel alloc] init];    self.progressTitle.textColor = titleColor;    self.progressTitle.textAlignment = NSTextAlignmentCenter;    self.progressTitle.font = [UIFont systemFontOfSize:titleFontSize];//    self.progressTitle.text = @"30秒";    [self.baseView addSubview:self.progressTitle];    self.progressView = [[UIProgressView alloc] init];    self.progressView.trackTintColor = [UIColor clearColor];    self.progressView.progressTintColor = TedcallStorageProgressColor;    [self.progressView setProgress:0.0];    [self.baseView addSubview:self.progressView];    // 屏幕锁    self.lockBtn = [UIButton buttonWithType:UIButtonTypeCustom];    [self.lockBtn setImage:[UIImage imageNamed:@"ic_sp_bf"] forState:UIControlStateNormal];    [self.lockBtn setImage:[UIImage imageNamed:@"ic_ks_bf"] forState:UIControlStateSelected];    [self.lockBtn addTarget:self action:@selector(lockClick) forControlEvents:UIControlEventTouchUpInside];    [self addSubview:self.lockBtn];}- (void)setVideoName:(NSString *)videoName{    _videoName = videoName;    self.nameLabel.text = videoName;}- (void)setCurrentTime:(NSString *)currentTime{    _currentTime = currentTime;    self.currentTimeLabel.text = currentTime;}- (void)setRemainingTime:(NSString *)remainingTime{    _remainingTime = remainingTime;    self.endTimeLabel.text = remainingTime;}- (void)setSliderValue:(float)sliderValue{    _sliderValue = sliderValue;    if (!self.isSliding) { // 防止滑动过程中的手动设值        [self .sliderView setValue:sliderValue animated:YES];    }}// 返回按钮监听- (void)backClick{    if (self.backBlock) {        self.backBlock(); // block返回回调    }}// 播放(暂停)监听- (void)playBtnClick{    NSLog(@"twoGesture");    self.playBtn.selected = !self.playBtn.selected;    [self changePlayBtnState:self.playBtn.selected];    if (self.playBlock) {        self.playBlock(self.playBtn);    }}// 屏幕锁监听- (void)lockClick{    self.lockBtn.selected = !self.lockBtn.selected;    if (self.lockBtn.selected) {        self.playView.userInteractionEnabled = NO;        [UIView transitionWithView:self.lockBtn duration:1.0 options:0 animations:^{            self.topView.alpha = 0.0;            self.bottomView.alpha = 0.0;            self.lockBtn.alpha = 0.0;        } completion:^(BOOL finished) {        }];    } else {        self.topView.alpha = 1.0;        self.bottomView.alpha = 1.0;        self.playView.userInteractionEnabled = YES;        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{            [UIView transitionWithView:self.lockBtn duration:1.0 options:0 animations:^{                self.topView.alpha = 0.0;                self.bottomView.alpha = 0.0;                self.lockBtn.alpha = 0.0;            } completion:^(BOOL finished) {            }];        });    }}- (void)changePlayBtnState:(BOOL)select{    self.playBtn.selected = select;    if (select) {        [self.playBtn setImage:[UIImage imageNamed:@"ic_bf_zt"] forState:UIControlStateNormal];    } else {        [self.playBtn setImage:[UIImage imageNamed:@"ic_bf_ks"] forState:UIControlStateNormal];    }}// 滑动结束监听- (void)sliderChange{//    NSLog(@"滑动结束");    self.isSliding = NO;    if (self.changeSliderBlock) {        self.changeSliderBlock(self.sliderView);    }}// 滑动监听- (void)slideringListening{//    NSLog(@"正在滑动");    if (!self.isSliding) {        self.isSliding = YES;    }}- (void)layoutSubviews{    [super layoutSubviews];    CGFloat width = self.frame.size.width;    CGFloat height = self.frame.size.height;    // 承载视频View    self.playView.frame = self.bounds;    // 顶部view    CGFloat topX = 0;    CGFloat topY = 0;    CGFloat topW = width;    CGFloat topH = viewHeight - 10;    self.topView.frame = CGRectMake(topX, topY, topW, topH);    // 返回按钮    CGFloat backW = 30.0;    CGFloat backH = backW;    CGFloat backX = space;    CGFloat backY = (topH - backH)/2;    self.backBtn.frame = CGRectMake(backX, backY, backW, backH);    // 视频名称    CGFloat nameX = space + CGRectGetMaxX(self.backBtn.frame);    CGFloat nameH = 20.0;    CGFloat nameW = width - 2*nameX;    CGFloat nameY = (topH - nameH)/2;    self.nameLabel.frame = CGRectMake(nameX, nameY, nameW, nameH);    // 底部view    CGFloat bottomX = 0;    CGFloat bottomY = height - viewHeight;    CGFloat bottomW = width;    CGFloat bottomH = viewHeight;    self.bottomView.frame = CGRectMake(bottomX, bottomY, bottomW, bottomH);    // 播放(暂停)按钮    CGFloat playW = 40.0;    CGFloat playH = playW;    CGFloat playX = space;    CGFloat playY = (viewHeight - playH)/2;    self.playBtn.frame = CGRectMake(playX, playY, playW, playH);    // 滑动条    CGFloat sliderX = space + CGRectGetMaxY(self.playBtn.frame);    CGFloat sliderH = 6;    CGFloat sliderW = width - sliderX - space;    CGFloat sliderY = playY + playH/2 - 4;    self.sliderView.frame = CGRectMake(sliderX, sliderY, sliderW, sliderH);    // 当前标签    CGFloat currentX = sliderX;    CGFloat currentY = CGRectGetMaxY(self.sliderView.frame);    CGFloat currentH = 20.0;    CGFloat currentW = sliderW/2;    self.currentTimeLabel.frame = CGRectMake(currentX, currentY, currentW, currentH);    // 结束标签    CGFloat endW = currentW;    CGFloat endX = CGRectGetMaxX(self.sliderView.frame) - endW;    CGFloat endY = currentY;    CGFloat endH = currentH;    self.endTimeLabel.frame = CGRectMake(endX, endY, endW, endH);    // 快进/快退view    CGFloat baseW = 140.0;    CGFloat baseH = 74.0;    CGFloat baseY = CGRectGetMaxY(self.topView.frame) + 20.0;    CGFloat baseX = (width - baseW)/2;    self.baseView.frame = CGRectMake(baseX, baseY, baseW, baseH);    CGFloat changeW = 30.0;    CGFloat changeH = 20.0;    CGFloat changeX = (baseW - changeW)/2;    CGFloat changeY = 8.0;    self.changeBtn.frame = CGRectMake(changeX, changeY, changeW, changeH);    CGFloat titleY = 8.0 + CGRectGetMaxY(self.changeBtn.frame);    CGFloat titleX = 0;    CGFloat titleW = baseW;    CGFloat titleH = 20.0;    self.progressTitle.frame = CGRectMake(titleX, titleY, titleW, titleH);    CGFloat progressX = 3.0;    CGFloat progressY = 8.0 + CGRectGetMaxY(self.progressTitle.frame);    CGFloat progressW = baseW - 2*progressX;    CGFloat progressH = 0.0;    self.progressView.frame = CGRectMake(progressX, progressY, progressW, progressH);    // 屏幕锁    CGFloat lockX = space;    CGFloat lockW = 50.0;    CGFloat lockH = 50.0;    CGFloat lockY = (height - lockH)/2;    self.lockBtn.frame = CGRectMake(lockX, lockY, lockW, lockH);}#pragma mark - -- 手势操作- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{    NSLog(@"touchesBegan");    if (self.lockBtn.selected) { // 锁屏状态        [UIView transitionWithView:self.lockBtn duration:1.0 options:0 animations:^{            self.lockBtn.alpha = 1.0;        } completion:^(BOOL finished) {            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{                if (self.lockBtn.selected) {                    [UIView transitionWithView:self.lockBtn duration:1.0 options:0 animations:^{                        self.lockBtn.alpha = 0.0;                    } completion:^(BOOL finished) {                    }];                }            });        }];    }}// 添加手势处理- (void)addGesture{    // 单点    UITapGestureRecognizer *oneGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(oneGestureClick)];    oneGesture.numberOfTapsRequired = 1; // 单击    oneGesture.numberOfTouchesRequired = 1; // 单指单击    [self.playView addGestureRecognizer:oneGesture];    // 双击    UITapGestureRecognizer *twoGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(playBtnClick)];    twoGesture.numberOfTapsRequired = 2; // 双击    twoGesture.numberOfTouchesRequired = 1; // 单指双击    [self.playView addGestureRecognizer:twoGesture];    // 长按    UILongPressGestureRecognizer *longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longGestureClick:)];    longGesture.minimumPressDuration = 3.0; // 长按3秒触发    [self.playView addGestureRecognizer:longGesture];    // 拖动    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureClick:)];    [self.playView addGestureRecognizer:panGesture];    //解决拖动和长按手势之间的冲突    [longGesture requireGestureRecognizerToFail:panGesture];    // 解决单击和双击手势的冲突    [oneGesture requireGestureRecognizerToFail:twoGesture];}// 单击手势监听- (void)oneGestureClick{    NSLog(@"oneGestureClick");    if (self.topView.alpha<=0.0) { // 显示        // 动画显示        [UIView transitionWithView:self.topView duration:1.0 options:0 animations:^{            self.topView.alpha = 1.0;            self.bottomView.alpha = 1.0;            self.lockBtn.alpha = 1.0;        } completion:^(BOOL finished) {            // 5秒后自动隐藏            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{                if (self.topView.alpha>0.0) {                    [self oneGestureClick];                }            });        }];    } else {        // 动画隐藏        [UIView transitionWithView:self.topView duration:1.0 options:0 animations:^{            self.topView.alpha = 0.0;            self.bottomView.alpha = 0.0;            self.lockBtn.alpha = 0.0;        } completion:^(BOOL finished) {        }];    }}// 长按监听- (void)longGestureClick:(UILongPressGestureRecognizer *)longGesture{    // 长按手势会调用多次监听方法,先判断手势状态    if (longGesture.state == UIGestureRecognizerStateBegan) {        NSLog(@"长按开始");    }}// 拖动监听- (void)panGestureClick:(UIPanGestureRecognizer *)panGesture{    CGPoint translation = [panGesture translationInView:self.playView]; // 取得相对位置的偏移点(相对位置为手指第一次在屏幕的点)    NSLog(@"translation:%@",NSStringFromCGPoint(translation));    if (panGesture.state == UIGestureRecognizerStateBegan){        NSLog (@"滑动开始");        self.beginPoint = translation;        self.currentPoint = translation;    }else if (panGesture.state == UIGestureRecognizerStateChanged){        self.moveDirection = [self determineCameraDirectionIfNeeded:translation];        switch (self.moveDirection) {            case PlayerMoveDirectionDown:                NSLog(@"PlayerMoveDirectionDown");                break;            case PlayerMoveDirectionUp:                NSLog(@"PlayerMoveDirectionUp");                break;            case PlayerMoveDirectionRight:            {                NSLog(@"PlayerMoveDirectionRight");                self.changeBtn.selected = NO;                self.progressTitle.text = CustomLocalizedString(@"快进", nil);                if (self.baseView.alpha == 0.0) {                    self.baseView.alpha = 1.0;                }            }                break;            case PlayerMoveDirectionLeft:            {                NSLog(@"PlayerMoveDirectionLeft");                self.changeBtn.selected = YES;                self.progressTitle.text = CustomLocalizedString(@"快退", nil);                if (self.baseView.alpha == 0.0) {                    self.baseView.alpha = 1.0;                }            }                break;            default :                break;        }        self.currentPoint = translation; // 刷新当前位置    }else if (panGesture.state == UIGestureRecognizerStateEnded){        NSLog (@"滑动结束");        [UIView transitionWithView:self.baseView duration:1.0 options:0 animations:^{            self.baseView.alpha = 0.0;        } completion:^(BOOL finished) {        }];        if (self.endPanGesture) {            self.endPanGesture(0.5,self.moveDirection);        }    }}- (PlayerMoveDirection) determineCameraDirectionIfNeeded:(CGPoint)translation{    // 设定一个幅度使拖动在不够水平(略微有点偏差)的方向上的处理,上下一般不处理    if (translation.x > self.currentPoint.x && (fabs(translation.y - self.currentPoint.y) <= gestureMinimumTranslation)){ // 说明水平向右拖动了        return PlayerMoveDirectionRight;    }else if(translation.x < self.currentPoint.x && (fabs(translation.y - self.currentPoint.y) <= gestureMinimumTranslation)){ // 说明水平向左        return PlayerMoveDirectionLeft;    }else if (translation.x == self.currentPoint.x && translation.y > self.currentPoint.y) { // 向下        return PlayerMoveDirectionDown;    } else if (translation.x == self.currentPoint.x && translation.y < self.currentPoint.y) { // 向上        return PlayerMoveDirectionUp;    } else{        return PlayerMoveDirectionNone;    }}- (void)updateFastImage:(int)type{    if (type == 4) { // 左    } else if (type == 3) { // 右    }}@endCustomSlider.h/CustomSlider.m(自定义滑块)////  CustomSlider.h//  TedcallStorage////  Created by  tedcall on 16/6/28.//  Copyright © 2016年 pocket. All rights reserved.//#import <UIKit/UIKit.h>@interface CustomSlider : UISlider@end////  CustomSlider.m//  TedcallStorage////  Created by  tedcall on 16/6/28.//  Copyright © 2016年 pocket. All rights reserved.//#import "CustomSlider.h"@implementation CustomSlider- (void)drawRect:(CGRect)rect{    UIImageView *imageView = nil;    // 取得滑块View    for (UIView *view in self.subviews) {        if ([view isKindOfClass:[UIImageView class]]) {            if (view.frame.size.width == view.frame.size.height) {                imageView = (UIImageView *)view;            }        }    }    if (imageView) { // 有值        CGFloat redViewW = 8.0;        CGFloat redViewH =redViewW;        CGFloat redViewX = (imageView.frame.size.width - redViewW)/2;        CGFloat redViewY = (imageView.frame.size.height - redViewH)/2;        UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(redViewX, redViewY, redViewW, redViewH)];        redView.backgroundColor = RGB(255, 255, 255, 0.7);        redView.layer.cornerRadius = redViewW/2;        redView.layer.masksToBounds = YES;        [imageView addSubview:redView];    }}// 重写进度条frame- (CGRect)trackRectForBounds:(CGRect)bounds {    return CGRectMake(0,0,bounds.size.width,6.0);}// 解决两边空隙问题- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value{    rect.origin.x = rect.origin.x - 10 ;    rect.size.width = rect.size.width +20;    return CGRectInset ([super thumbRectForBounds:bounds trackRect:rect value:value], 10 , 10);}@end

文/Pocket(简书作者)
原文链接:http://www.jianshu.com/p/178627b085c3

0 0
原创粉丝点击