ZQPlayerMaskView.m 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. //
  2. // ZQPlayerMaskView.m
  3. // ZQPlayer
  4. //
  5. // Created by wang on 2018/3/16.
  6. // Copyright © 2018年 qigge. All rights reserved.
  7. //
  8. #import "ZQPlayerMaskView.h"
  9. #import "Masonry.h"
  10. @interface ZQPlayerMaskView ()<ZQPlayerDelegate,UIGestureRecognizerDelegate> {
  11. NSString *_playUrl;
  12. BOOL _isDragSlider;
  13. }
  14. /** 播放器 */
  15. @property (nonatomic, strong) ZQPlayer *player;
  16. /** 背景图片 */
  17. @property (nonatomic, strong) UIImageView *backgroundImage;
  18. // 控件
  19. @property (nonatomic, strong) UIButton *backBtn; // 全屏后的返回按钮
  20. @property (nonatomic, strong) UIView *bottomView; // 底部包含,播放、当前时间、总时间、进度条等视图
  21. @property (nonatomic, strong) UIButton *playBtn; // 播放按钮
  22. @property (nonatomic, strong) UILabel *currentTimeLabel; // 当前时间
  23. @property (nonatomic, strong) UILabel *totalTimeLabel; // 总时间
  24. @property (nonatomic, strong) UIProgressView *progressView; // 加载进度条
  25. @property (nonatomic, strong) UISlider *videoSlider; // 视频播放进度条
  26. /** 定时隐藏buttomView和TopView的定时器 */
  27. @property (nonatomic,strong) NSTimer *hideBottomTimer;
  28. // 手势
  29. @property(nonatomic, strong) UIPanGestureRecognizer *pan; // 快进,快退手势
  30. @property(nonatomic, strong) UITapGestureRecognizer *sliderTap; // 视频播放进度条点击快进、快退手势
  31. @property(nonatomic, strong) UITapGestureRecognizer *tap; // 点击显示控件手势
  32. /** 加载中View */
  33. @property (nonatomic, strong) UIView *loadingView;
  34. @property (nonatomic, strong) UIImageView *loadingImage;
  35. @end
  36. @implementation ZQPlayerMaskView
  37. - (instancetype)initWithFrame:(CGRect)frame {
  38. if (self = [super initWithFrame:frame]) {
  39. self.backgroundColor = [UIColor blackColor];
  40. _isDragSlider = NO;
  41. _isWiFi = YES;
  42. [self setUI];
  43. }
  44. return self;
  45. }
  46. - (void)layoutSubviews {
  47. [super layoutSubviews];
  48. _player.playerLayer.frame = self.bounds;
  49. }
  50. - (void)setUI {
  51. // 添加平移手势,用来控制音量、亮度、快进快退
  52. _pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panDirection:)];
  53. [self addGestureRecognizer:_pan];
  54. UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(showOrHidden:)];
  55. tap.delegate = self;
  56. [self addGestureRecognizer:tap];
  57. [self addSubview:self.backgroundImage];
  58. self.player.playerLayer.frame = self.bounds;
  59. if (![self.layer.sublayers containsObject:self.player.playerLayer]) {
  60. [self.layer addSublayer:self.player.playerLayer];
  61. }
  62. [self addSubview:self.backBtn];
  63. [self addSubview:self.bottomView];
  64. [_bottomView addSubview:self.playBtn];
  65. [_bottomView addSubview:self.currentTimeLabel];
  66. [_bottomView addSubview:self.fullBtn];
  67. [_bottomView addSubview:self.progressView];
  68. [_bottomView addSubview:self.videoSlider];
  69. [_bottomView addSubview:self.totalTimeLabel];
  70. [self addSubview:self.loadingView];
  71. [_backBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  72. make.left.equalTo(self).with.offset(15);
  73. make.top.equalTo(self).with.offset(18);
  74. }];
  75. [_bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
  76. make.left.right.bottom.equalTo(self);
  77. make.height.mas_equalTo(40);
  78. }];
  79. [_playBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  80. make.left.equalTo(self.bottomView).with.offset(20);
  81. make.bottom.equalTo(self.bottomView).with.offset(-10);
  82. make.size.mas_equalTo(CGSizeMake(20, 20));
  83. }];
  84. [_currentTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  85. make.left.equalTo(self.playBtn.mas_right).with.offset(10);
  86. make.centerY.equalTo(self.playBtn);
  87. make.width.mas_equalTo(38);
  88. }];
  89. [_fullBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  90. make.right.equalTo(self.bottomView).with.offset(-20);
  91. make.centerY.equalTo(self.playBtn);
  92. }];
  93. [_totalTimeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  94. make.right.equalTo(self.fullBtn.mas_left).with.offset(-10);
  95. make.centerY.equalTo(self.playBtn);
  96. }];
  97. [_progressView mas_makeConstraints:^(MASConstraintMaker *make) {
  98. make.left.equalTo(self.currentTimeLabel.mas_right).with.offset(10);
  99. make.right.equalTo(self.totalTimeLabel.mas_left).with.offset(-10);
  100. make.centerY.equalTo(self.playBtn);
  101. }];
  102. [_videoSlider mas_makeConstraints:^(MASConstraintMaker *make) {
  103. make.left.equalTo(self.currentTimeLabel.mas_right).with.offset(10);
  104. make.right.equalTo(self.totalTimeLabel.mas_left).with.offset(-10);
  105. make.centerY.equalTo(self.playBtn).with.offset(-1);
  106. }];
  107. [_loadingView mas_makeConstraints:^(MASConstraintMaker *make) {
  108. make.centerX.equalTo(self);
  109. make.centerY.equalTo(self).with.offset(10);
  110. make.size.mas_equalTo(CGSizeMake(90, 70));
  111. }];
  112. }
  113. #pragma mark - public method
  114. - (void)playWithVideoUrl:(NSString *)videoUrl {
  115. if (videoUrl && videoUrl.length > 0 && ![_playUrl isEqualToString:videoUrl]) {
  116. self.videoSlider.value = 0;
  117. _currentTimeLabel.text = @"00:00";
  118. _playUrl = videoUrl;
  119. if (_isWiFi) {
  120. [_player nextWithUrl:videoUrl];
  121. [_player play];
  122. }else{
  123. [self playWithJudgeNet];
  124. }
  125. }
  126. }
  127. #pragma mark - private method
  128. // 从ZQPlayerImage.bundle 中加载图片
  129. - (UIImage *)imagesNamedFromCustomBundle:(NSString *)imgName {
  130. NSString *bundlePath = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:@"ZQPlayerImage.bundle"];
  131. NSString *img_path = [bundlePath stringByAppendingPathComponent:imgName];
  132. return [UIImage imageWithContentsOfFile:img_path];
  133. }
  134. // 播放视频,判断用户网络来
  135. - (void)playWithJudgeNet {
  136. if (_isWiFi) {
  137. [_player play];
  138. }else {
  139. UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"提示"
  140. message:@"您正处于移动网络环境下,是否要使用流量播放"
  141. preferredStyle:UIAlertControllerStyleAlert];
  142. [alertC addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  143. self.isWiFi = YES;
  144. [self.player nextWithUrl:self->_playUrl];
  145. [self.player play];
  146. }]];
  147. [alertC addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
  148. self.playBtn.selected = NO;
  149. }]];
  150. [[[UIApplication sharedApplication] keyWindow].rootViewController presentViewController:alertC animated:YES completion:nil];
  151. }
  152. }
  153. #pragma mark - UIGestureRecognizerDelegate
  154. - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
  155. if (_sliderTap == gestureRecognizer) {
  156. return _videoSlider == gestureRecognizer.view;
  157. }else {
  158. return self == gestureRecognizer.view;
  159. }
  160. }
  161. #pragma mark - slider事件
  162. // slider开始滑动事件
  163. - (void)progressSliderTouchBegan:(UISlider *)slider {
  164. _isDragSlider = YES;
  165. [_player.player pause];
  166. if (_hideBottomTimer) {
  167. [_hideBottomTimer invalidate];
  168. _hideBottomTimer = nil;
  169. }
  170. [self showOrHideWith:YES];
  171. }
  172. // slider滑动中事件
  173. - (void)progressSliderValueChanged:(UISlider *)slider {
  174. CGFloat current = _player.timeInterval*slider.value;
  175. //秒数
  176. NSInteger proSec = (NSInteger)current%60;
  177. //分钟
  178. NSInteger proMin = (NSInteger)current/60;
  179. _currentTimeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld", proMin, proSec];
  180. }
  181. // slider结束滑动事件
  182. - (void)progressSliderTouchEnded:(UISlider *)slider {
  183. if (_player.player.status != AVPlayerStatusReadyToPlay) {
  184. return;
  185. }
  186. //转换成CMTime才能给player来控制播放进度
  187. __weak typeof(self) weakself = self;
  188. CMTime dragedCMTime = CMTimeMakeWithSeconds(_player.timeInterval * slider.value, 600);
  189. [_player.player seekToTime:dragedCMTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
  190. __strong typeof(weakself) strongself = self;
  191. strongself->_isDragSlider = NO;
  192. if (finished) {
  193. if (weakself.player.isPlaying) {
  194. [weakself.player.player play];
  195. }
  196. }
  197. }];
  198. [self hidePlayerSubviewWithTimer];
  199. }
  200. - (void)tapSlider:(UITapGestureRecognizer *)tap {
  201. [self progressSliderTouchBegan:self.videoSlider];
  202. CGPoint point = [tap locationInView:tap.view];
  203. CGFloat value = point.x/ tap.view.frame.size.width;
  204. self.videoSlider.value = value;
  205. [self progressSliderValueChanged:self.videoSlider];
  206. [self progressSliderTouchEnded:self.videoSlider];
  207. }
  208. #pragma mark - ZQPlayerDelegate
  209. /**
  210. 播放器状态变化
  211. @param player 播放器
  212. @param state 状态
  213. */
  214. - (void)ZQPlayerStateChange:(ZQPlayer *)player state:(ZQPlayerState)state {
  215. if (self.delegate && [self.delegate respondsToSelector:@selector(ZQPlayerStateChange:state:)]) {
  216. [self.delegate ZQPlayerStateChange:player state:state];
  217. }
  218. if (state == ZQPlayerStatePlaying) {
  219. _playBtn.selected = YES;
  220. if (_player.isBuffering) {
  221. [self startLoading];
  222. }else {
  223. self.loadingView.hidden = YES;
  224. [self hidePlayerSubviewWithTimer];
  225. }
  226. }
  227. else if (state == ZQPlayerStatePause) {
  228. _playBtn.selected = NO;
  229. [self showPlayerSubview];
  230. }
  231. else if (state == ZQPlayerStateBufferEmpty) {
  232. [self startLoading];
  233. }
  234. else if (state == ZQPlayerStateKeepUp) {
  235. [self stopLoading];
  236. }
  237. else if (state == ZQPlayerStateStop) {
  238. _playBtn.selected = NO;
  239. _currentTimeLabel.text = @"00:00";
  240. [_videoSlider setValue:0 animated:YES];
  241. [self showPlayerSubview];
  242. }
  243. else if (state == ZQPlayerStateReadyToPlay) {
  244. }
  245. }
  246. /**
  247. 视频源开始加载后调用 ,返回视频的长度
  248. */
  249. - (void)ZQPlayerTotalTime:(ZQPlayer *)player totalTime:(CGFloat)time {
  250. if (self.delegate && [self.delegate respondsToSelector:@selector(ZQPlayerTotalTime:totalTime:)]) {
  251. [self.delegate ZQPlayerTotalTime:player totalTime:time];
  252. }
  253. //秒数
  254. NSInteger proSec = (NSInteger)time%60;
  255. //分钟
  256. NSInteger proMin = (NSInteger)time/60;
  257. _totalTimeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld", proMin, proSec];
  258. }
  259. /**
  260. 视频源加载时调用 ,返回视频的缓冲长度
  261. */
  262. - (void)ZQPlayerLoadTime:(ZQPlayer *)player loadTime:(CGFloat)time {
  263. if (self.delegate && [self.delegate respondsToSelector:@selector(ZQPlayerLoadTime:loadTime:)]) {
  264. [self.delegate ZQPlayerLoadTime:player loadTime:time];
  265. }
  266. [_progressView setProgress:time / player.timeInterval animated:YES];
  267. }
  268. /**
  269. 播放时调用,返回当前时间
  270. */
  271. - (void)ZQPlayerCurrentTime:(ZQPlayer *)player currentTime:(CGFloat)time {
  272. if (self.delegate && [self.delegate respondsToSelector:@selector(ZQPlayerCurrentTime:currentTime:)]) {
  273. [self.delegate ZQPlayerCurrentTime:player currentTime:time];
  274. }
  275. [self.videoSlider setValue:time/player.timeInterval animated:YES];
  276. //秒数
  277. NSInteger proSec = (NSInteger)time%60;
  278. //分钟
  279. NSInteger proMin = (NSInteger)time/60;
  280. _currentTimeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld", proMin, proSec];
  281. }
  282. #pragma mark - Events
  283. // 是否显示控件
  284. - (void)showOrHideWith:(BOOL)isShow {
  285. [UIView animateWithDuration:0.3 animations:^{
  286. self.bottomView.hidden = !isShow;
  287. }];
  288. // 判断横屏还是竖屏 ,横屏显示返回按钮
  289. UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
  290. if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
  291. _backBtn.hidden = YES;
  292. }else {
  293. _backBtn.hidden = !isShow;
  294. }
  295. }
  296. // 开始加载
  297. - (void)startLoading {
  298. if (!_player.isPlaying) {
  299. return;
  300. }
  301. if (_hideBottomTimer) {
  302. [_hideBottomTimer invalidate];
  303. _hideBottomTimer = nil;
  304. }
  305. [self showOrHideWith:YES]; // 显示控件
  306. self.loadingView.hidden = NO;
  307. self.loadingImage.image = [self imagesNamedFromCustomBundle:@"icon_video_loading"];
  308. if (![self.loadingImage.layer animationForKey:@"loading"]) {
  309. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
  310. //默认是顺时针效果,若将fromValue和toValue的值互换,则为逆时针效果
  311. animation.fromValue = [NSNumber numberWithFloat:0.0f];
  312. animation.toValue = [NSNumber numberWithFloat: M_PI *2];
  313. animation.duration = 3;
  314. animation.autoreverses = NO;
  315. animation.fillMode = kCAFillModeForwards;
  316. animation.repeatCount = MAXFLOAT; //如果这里想设置成一直自旋转,可以设置为MAXFLOAT,否则设置具体的数值则代表执行多少次
  317. [self.loadingImage.layer addAnimation:animation forKey:@"loading"];
  318. }
  319. }
  320. // 加载完成
  321. - (void)stopLoading {
  322. if (!_player.isPlaying) {
  323. return;
  324. }
  325. if (_player.isPlaying) {
  326. self.loadingView.hidden = YES;
  327. [self.loadingImage.layer removeAnimationForKey:@"loading"];
  328. // 自动隐藏控件
  329. [self hidePlayerSubviewWithTimer];
  330. }
  331. }
  332. // 4秒后自动隐藏底部视图
  333. - (void)hidePlayerSubviewWithTimer {
  334. if (_hideBottomTimer) {
  335. [_hideBottomTimer invalidate];
  336. _hideBottomTimer = nil;
  337. }
  338. // 开启定时器
  339. _hideBottomTimer = [NSTimer timerWithTimeInterval:4 target:self selector:@selector(hidePlayerSubview) userInfo:nil repeats:NO];
  340. [[NSRunLoop mainRunLoop] addTimer:_hideBottomTimer forMode:NSRunLoopCommonModes];
  341. }
  342. // 隐藏底部试图
  343. - (void) hidePlayerSubview {
  344. if (!_player.isPlaying) {
  345. return;
  346. }
  347. if (_hideBottomTimer) {
  348. [_hideBottomTimer invalidate];
  349. _hideBottomTimer = nil;
  350. }
  351. [self showOrHideWith:NO];
  352. }
  353. // 显示底部试图
  354. - (void)showPlayerSubview {
  355. if (_hideBottomTimer) {
  356. [_hideBottomTimer invalidate];
  357. _hideBottomTimer = nil;
  358. }
  359. [self showOrHideWith:YES];
  360. if (_player.isPlaying) {
  361. [self hidePlayerSubviewWithTimer];
  362. }
  363. }
  364. #pragma mark - 手势 和按钮事件
  365. // 点击手势 显示和隐藏播放器上其他视图
  366. - (void)showOrHidden:(UITapGestureRecognizer *)gr {
  367. if (_player.isPlaying) {
  368. if (_bottomView.hidden) {
  369. [self showPlayerSubview];
  370. }else {
  371. [self hidePlayerSubview];
  372. }
  373. }
  374. }
  375. //添加平移手势 快进快退
  376. - (void)panDirection:(UIPanGestureRecognizer *)pan {
  377. CGPoint veloctyPoint = [pan velocityInView:self];
  378. // 判断是垂直移动还是水平移动
  379. switch (pan.state) {
  380. case UIGestureRecognizerStateBegan:{ // 开始移动
  381. // 使用绝对值来判断移动的方向
  382. CGFloat x = fabs(veloctyPoint.x);
  383. CGFloat y = fabs(veloctyPoint.y);
  384. if (x > y) { // 水平移动
  385. [self progressSliderTouchBegan:_videoSlider];
  386. }else if (x < y){ // 垂直移动
  387. }
  388. break;
  389. }
  390. case UIGestureRecognizerStateChanged:{ // 正在移动
  391. float v = _videoSlider.value + veloctyPoint.x/40000;
  392. [_videoSlider setValue:v animated:YES];
  393. [self progressSliderValueChanged:_videoSlider];
  394. break;
  395. }
  396. case UIGestureRecognizerStateEnded:{ // 移动停止
  397. [self progressSliderTouchEnded:_videoSlider];
  398. }
  399. default:
  400. break;
  401. }
  402. }
  403. #pragma mark - 按钮事件
  404. // 播放按钮事件
  405. - (void)startAndPause:(UIButton *)btn {
  406. btn.selected = !btn.selected;
  407. if (btn.selected) {
  408. [self playWithJudgeNet];
  409. }else {
  410. [_player pause];
  411. }
  412. }
  413. // lodingView上的View点击手势 暂停后,点击播放
  414. - (void)play {
  415. if (!_player.isPlaying) {
  416. [self playWithJudgeNet];
  417. }
  418. }
  419. /** 全屏 和退出全屏 */
  420. - (void)videoFullAction:(UIButton *)btn {
  421. UIDeviceOrientation orientation;
  422. UIInterfaceOrientation orgOrientation = [UIApplication sharedApplication].statusBarOrientation;
  423. if (orgOrientation == UIInterfaceOrientationPortrait || orgOrientation == UIInterfaceOrientationPortraitUpsideDown) {
  424. orientation = UIDeviceOrientationLandscapeLeft;
  425. _backBtn.hidden = NO;
  426. }else {
  427. orientation = UIDeviceOrientationPortrait;
  428. _backBtn.hidden = YES;
  429. }
  430. if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
  431. SEL selector = NSSelectorFromString(@"setOrientation:");
  432. NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
  433. [invocation setSelector:selector];
  434. [invocation setTarget:[UIDevice currentDevice]];
  435. int val = orientation;
  436. [invocation setArgument:&val atIndex:2];
  437. [invocation invoke];
  438. }
  439. }
  440. #pragma mark - Getter & Setter
  441. - (UIButton *)backBtn {
  442. if (!_backBtn) {
  443. _backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  444. _backBtn.hidden = YES;
  445. _backBtn.titleLabel.font = [UIFont systemFontOfSize:17];
  446. [_backBtn setImage:[self imagesNamedFromCustomBundle:@"icon_back_white"] forState:UIControlStateNormal];
  447. [_backBtn addTarget:self action:@selector(videoFullAction:) forControlEvents:UIControlEventTouchUpInside];
  448. }
  449. return _backBtn;
  450. }
  451. - (UIButton *)playBtn {
  452. if (!_playBtn) {
  453. _playBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  454. _playBtn.frame = CGRectMake(0, 0, 21, 21);
  455. [_playBtn setImage:[self imagesNamedFromCustomBundle:@"icon_video_play"] forState:UIControlStateNormal];
  456. [_playBtn setImage:[self imagesNamedFromCustomBundle:@"icon_video_stop"] forState:UIControlStateSelected];
  457. [_playBtn addTarget:self action:@selector(startAndPause:) forControlEvents:UIControlEventTouchUpInside];
  458. }
  459. return _playBtn;
  460. }
  461. - (UIButton *)fullBtn {
  462. if (!_fullBtn) {
  463. _fullBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  464. _fullBtn.frame = CGRectMake(0, 0, 21, 21);
  465. [_fullBtn setImage:[self imagesNamedFromCustomBundle:@"icon_video_fullscreen"] forState:UIControlStateNormal];
  466. [_fullBtn addTarget:self action:@selector(videoFullAction:) forControlEvents:UIControlEventTouchUpInside];
  467. }
  468. return _fullBtn;
  469. }
  470. - (UIView *)bottomView {
  471. if (!_bottomView) {
  472. _bottomView = [[UIView alloc] init];
  473. _bottomView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
  474. }
  475. return _bottomView;
  476. }
  477. - (UILabel *)currentTimeLabel {
  478. if (!_currentTimeLabel) {
  479. _currentTimeLabel = [[UILabel alloc]init];
  480. _currentTimeLabel.text = @"00:00";
  481. _currentTimeLabel.textColor = [UIColor whiteColor];
  482. _currentTimeLabel.textAlignment = NSTextAlignmentCenter;
  483. _currentTimeLabel.font = [UIFont systemFontOfSize:11];
  484. }
  485. return _currentTimeLabel;
  486. }
  487. - (UILabel *)totalTimeLabel {
  488. if (!_totalTimeLabel) {
  489. _totalTimeLabel = [[UILabel alloc]init];
  490. _totalTimeLabel.textAlignment = NSTextAlignmentCenter;
  491. _totalTimeLabel.font = [UIFont systemFontOfSize:11];
  492. _totalTimeLabel.textColor = [UIColor whiteColor];
  493. _totalTimeLabel.text = @"00:00";
  494. }
  495. return _totalTimeLabel;
  496. }
  497. - (UIProgressView *)progressView {
  498. if (!_progressView) {
  499. _progressView = [[UIProgressView alloc]init];
  500. _progressView.progressTintColor = [UIColor colorWithWhite:1 alpha:0.3];
  501. _progressView.trackTintColor = [UIColor colorWithRed:81/255.0 green:81/255.0 blue:81/255.0 alpha:0.5];
  502. }
  503. return _progressView;
  504. }
  505. - (UISlider *)videoSlider {
  506. if (!_videoSlider) {
  507. _videoSlider = [[UISlider alloc]init];
  508. [_videoSlider setThumbImage:[self imagesNamedFromCustomBundle:@"icon_video_spot"] forState:UIControlStateNormal];
  509. _videoSlider.minimumTrackTintColor = [UIColor colorWithWhite:1 alpha:0.6];
  510. _videoSlider.maximumTrackTintColor = [UIColor clearColor];
  511. // slider开始滑动事件
  512. [_videoSlider addTarget:self action:@selector(progressSliderTouchBegan:) forControlEvents:UIControlEventTouchDown];
  513. // slider滑动中事件
  514. [_videoSlider addTarget:self action:@selector(progressSliderValueChanged:) forControlEvents:UIControlEventValueChanged];
  515. // slider结束滑动事件
  516. [_videoSlider addTarget:self action:@selector(progressSliderTouchEnded:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchCancel | UIControlEventTouchUpOutside];
  517. _sliderTap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapSlider:)];
  518. _sliderTap.delegate = self;
  519. [_videoSlider addGestureRecognizer:_sliderTap];
  520. }
  521. return _videoSlider;
  522. }
  523. - (UIView *)loadingView {
  524. if (!_loadingView) {
  525. _loadingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 70, 70)];
  526. _loadingView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
  527. _loadingView.layer.cornerRadius = 7;
  528. [_loadingView addSubview:self.loadingImage];
  529. [_loadingImage mas_makeConstraints:^(MASConstraintMaker *make) {
  530. make.center.equalTo(self->_loadingView);
  531. make.size.mas_equalTo(CGSizeMake(31, 31));
  532. }];
  533. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(play)];
  534. [_loadingView addGestureRecognizer:tap];
  535. }
  536. return _loadingView;
  537. }
  538. - (UIImageView *)loadingImage {
  539. if (!_loadingImage ){
  540. _loadingImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 31, 31)];
  541. _loadingImage.image = [self imagesNamedFromCustomBundle:@"icon_video_play"];
  542. _loadingImage.userInteractionEnabled = YES;
  543. }
  544. return _loadingImage;
  545. }
  546. - (UIImageView *)backgroundImage {
  547. if (!_backgroundImage) {
  548. _backgroundImage = [[UIImageView alloc] initWithFrame:self.bounds];
  549. }
  550. return _backgroundImage;
  551. }
  552. - (ZQPlayer *)player {
  553. if (!_player) {
  554. _player = [[ZQPlayer alloc] init];
  555. _player.delegate = self;
  556. }
  557. return _player;
  558. }
  559. - (void)dealloc {
  560. if (_hideBottomTimer) {
  561. [_hideBottomTimer invalidate];
  562. _hideBottomTimer = nil;
  563. }
  564. }
  565. @end