ZQPlayerLandSpaceViewController.m 23 KB

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