ZFPlayerControlView.m 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. //
  2. // ZFPlayerControlView.m
  3. // ZFPlayer
  4. //
  5. // Copyright (c) 2016年 任子丰 ( http://github.com/renzifeng )
  6. //
  7. // Permission is hereby granted, free of charge, to any person obtaining a copy
  8. // of this software and associated documentation files (the "Software"), to deal
  9. // in the Software without restriction, including without limitation the rights
  10. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. // copies of the Software, and to permit persons to whom the Software is
  12. // furnished to do so, subject to the following conditions:
  13. //
  14. // The above copyright notice and this permission notice shall be included in
  15. // all copies or substantial portions of the Software.
  16. //
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. // THE SOFTWARE.
  24. #import "ZFPlayerControlView.h"
  25. #import <AVKit/AVKit.h>
  26. #import <AVFoundation/AVFoundation.h>
  27. #import "UIView+ZFFrame.h"
  28. #import "ZFSliderView.h"
  29. #import "ZFUtilities.h"
  30. #import "UIImageView+ZFCache.h"
  31. #import <MediaPlayer/MediaPlayer.h>
  32. #import "ZFVolumeBrightnessView.h"
  33. #if __has_include(<ZFPlayer/ZFPlayer.h>)
  34. #import <ZFPlayer/ZFPlayerConst.h>
  35. #else
  36. #import "ZFPlayerConst.h"
  37. #endif
  38. @interface ZFPlayerControlView () <ZFSliderViewDelegate>
  39. /// 竖屏控制层的View
  40. @property (nonatomic, strong) ZFPortraitControlView *portraitControlView;
  41. /// 横屏控制层的View
  42. @property (nonatomic, strong) ZFLandScapeControlView *landScapeControlView;
  43. /// 加载loading
  44. @property (nonatomic, strong) ZFSpeedLoadingView *activity;
  45. /// 快进快退View
  46. @property (nonatomic, strong) UIView *fastView;
  47. /// 快进快退进度progress
  48. @property (nonatomic, strong) ZFSliderView *fastProgressView;
  49. /// 快进快退时间
  50. @property (nonatomic, strong) UILabel *fastTimeLabel;
  51. /// 快进快退ImageView
  52. @property (nonatomic, strong) UIImageView *fastImageView;
  53. /// 加载失败按钮
  54. @property (nonatomic, strong) UIButton *failBtn;
  55. /// 底部播放进度
  56. @property (nonatomic, strong) ZFSliderView *bottomPgrogress;
  57. /// 是否显示了控制层
  58. @property (nonatomic, assign, getter=isShowing) BOOL showing;
  59. /// 是否播放结束
  60. @property (nonatomic, assign, getter=isPlayEnd) BOOL playeEnd;
  61. @property (nonatomic, assign) BOOL controlViewAppeared;
  62. @property (nonatomic, assign) NSTimeInterval sumTime;
  63. @property (nonatomic, strong) dispatch_block_t afterBlock;
  64. @property (nonatomic, strong) ZFSmallFloatControlView *floatControlView;
  65. @property (nonatomic, strong) ZFVolumeBrightnessView *volumeBrightnessView;
  66. @property (nonatomic, strong) UIImageView *bgImgView;
  67. @property (nonatomic, strong) UIView *effectView;
  68. @end
  69. @implementation ZFPlayerControlView
  70. @synthesize player = _player;
  71. - (instancetype)initWithFrame:(CGRect)frame {
  72. self = [super initWithFrame:frame];
  73. if (self) {
  74. [self addAllSubViews];
  75. self.landScapeControlView.hidden = YES;
  76. self.floatControlView.hidden = YES;
  77. self.seekToPlay = YES;
  78. self.effectViewShow = YES;
  79. self.horizontalPanShowControlView = YES;
  80. self.autoFadeTimeInterval = 0.25;
  81. self.autoHiddenTimeInterval = 2.5;
  82. [[NSNotificationCenter defaultCenter] addObserver:self
  83. selector:@selector(volumeChanged:)
  84. name:@"AVSystemController_SystemVolumeDidChangeNotification"
  85. object:nil];
  86. }
  87. return self;
  88. }
  89. - (void)layoutSubviews {
  90. [super layoutSubviews];
  91. CGFloat min_x = 0;
  92. CGFloat min_y = 0;
  93. CGFloat min_w = 0;
  94. CGFloat min_h = 0;
  95. CGFloat min_view_w = self.zf_width;
  96. CGFloat min_view_h = self.zf_height;
  97. self.portraitControlView.frame = self.bounds;
  98. self.landScapeControlView.frame = self.bounds;
  99. self.floatControlView.frame = self.bounds;
  100. self.coverImageView.frame = self.bounds;
  101. self.bgImgView.frame = self.bounds;
  102. self.effectView.frame = self.bounds;
  103. min_w = 80;
  104. min_h = 80;
  105. self.activity.frame = CGRectMake(min_x, min_y, min_w, min_h);
  106. self.activity.zf_centerX = self.zf_centerX;
  107. self.activity.zf_centerY = self.zf_centerY + 10;
  108. min_w = 150;
  109. min_h = 30;
  110. self.failBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
  111. self.failBtn.center = self.center;
  112. min_w = 140;
  113. min_h = 80;
  114. self.fastView.frame = CGRectMake(min_x, min_y, min_w, min_h);
  115. self.fastView.center = self.center;
  116. min_w = 32;
  117. min_x = (self.fastView.zf_width - min_w) / 2;
  118. min_y = 5;
  119. min_h = 32;
  120. self.fastImageView.frame = CGRectMake(min_x, min_y, min_w, min_h);
  121. min_x = 0;
  122. min_y = self.fastImageView.zf_bottom + 2;
  123. min_w = self.fastView.zf_width;
  124. min_h = 20;
  125. self.fastTimeLabel.frame = CGRectMake(min_x, min_y, min_w, min_h);
  126. min_x = 12;
  127. min_y = self.fastTimeLabel.zf_bottom + 5;
  128. min_w = self.fastView.zf_width - 2 * min_x;
  129. min_h = 10;
  130. self.fastProgressView.frame = CGRectMake(min_x, min_y, min_w, min_h);
  131. min_x = 0;
  132. min_y = min_view_h - 1;
  133. min_w = min_view_w;
  134. min_h = 1;
  135. self.bottomPgrogress.frame = CGRectMake(min_x, min_y, min_w, min_h);
  136. min_x = 0;
  137. min_y = iPhoneX ? 54 : 30;
  138. min_w = 170;
  139. min_h = 35;
  140. self.volumeBrightnessView.frame = CGRectMake(min_x, min_y, min_w, min_h);
  141. self.volumeBrightnessView.zf_centerX = self.zf_centerX;
  142. }
  143. - (void)dealloc {
  144. [[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];
  145. [self cancelAutoFadeOutControlView];
  146. }
  147. /// 添加所有子控件
  148. - (void)addAllSubViews {
  149. [self addSubview:self.portraitControlView];
  150. [self addSubview:self.landScapeControlView];
  151. [self addSubview:self.floatControlView];
  152. [self addSubview:self.activity];
  153. [self addSubview:self.failBtn];
  154. [self addSubview:self.fastView];
  155. [self.fastView addSubview:self.fastImageView];
  156. [self.fastView addSubview:self.fastTimeLabel];
  157. [self.fastView addSubview:self.fastProgressView];
  158. [self addSubview:self.bottomPgrogress];
  159. [self addSubview:self.volumeBrightnessView];
  160. }
  161. - (void)autoFadeOutControlView {
  162. self.controlViewAppeared = YES;
  163. [self cancelAutoFadeOutControlView];
  164. @weakify(self)
  165. self.afterBlock = dispatch_block_create(0, ^{
  166. @strongify(self)
  167. [self hideControlViewWithAnimated:YES];
  168. });
  169. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.autoHiddenTimeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(),self.afterBlock);
  170. }
  171. /// 取消延时隐藏controlView的方法
  172. - (void)cancelAutoFadeOutControlView {
  173. if (self.afterBlock) {
  174. dispatch_block_cancel(self.afterBlock);
  175. self.afterBlock = nil;
  176. }
  177. }
  178. /// 隐藏控制层
  179. - (void)hideControlViewWithAnimated:(BOOL)animated {
  180. self.controlViewAppeared = NO;
  181. if (self.controlViewAppearedCallback) {
  182. self.controlViewAppearedCallback(NO);
  183. }
  184. [UIView animateWithDuration:animated ? self.autoFadeTimeInterval : 0 animations:^{
  185. if (self.player.isFullScreen) {
  186. [self.landScapeControlView hideControlView];
  187. } else {
  188. if (!self.player.isSmallFloatViewShow) {
  189. [self.portraitControlView hideControlView];
  190. }
  191. }
  192. } completion:^(BOOL finished) {
  193. self.bottomPgrogress.hidden = NO;
  194. }];
  195. }
  196. /// 显示控制层
  197. - (void)showControlViewWithAnimated:(BOOL)animated {
  198. self.controlViewAppeared = YES;
  199. if (self.controlViewAppearedCallback) {
  200. self.controlViewAppearedCallback(YES);
  201. }
  202. [self autoFadeOutControlView];
  203. [UIView animateWithDuration:animated ? self.autoFadeTimeInterval : 0 animations:^{
  204. if (self.player.isFullScreen) {
  205. [self.landScapeControlView showControlView];
  206. } else {
  207. if (!self.player.isSmallFloatViewShow) {
  208. [self.portraitControlView showControlView];
  209. }
  210. }
  211. } completion:^(BOOL finished) {
  212. self.bottomPgrogress.hidden = YES;
  213. }];
  214. }
  215. /// 音量改变的通知
  216. - (void)volumeChanged:(NSNotification *)notification {
  217. NSDictionary *userInfo = notification.userInfo;
  218. NSString *reasonstr = userInfo[@"AVSystemController_AudioVolumeChangeReasonNotificationParameter"];
  219. if ([reasonstr isEqualToString:@"ExplicitVolumeChange"]) {
  220. float volume = [ userInfo[@"AVSystemController_AudioVolumeNotificationParameter"] floatValue];
  221. if (self.player.isFullScreen) {
  222. [self.volumeBrightnessView updateProgress:volume withVolumeBrightnessType:ZFVolumeBrightnessTypeVolume];
  223. } else {
  224. [self.volumeBrightnessView addSystemVolumeView];
  225. }
  226. }
  227. }
  228. #pragma mark - Public Method
  229. /// 重置控制层
  230. - (void)resetControlView {
  231. [self.portraitControlView resetControlView];
  232. [self.landScapeControlView resetControlView];
  233. [self cancelAutoFadeOutControlView];
  234. self.bottomPgrogress.value = 0;
  235. self.bottomPgrogress.bufferValue = 0;
  236. self.floatControlView.hidden = YES;
  237. self.failBtn.hidden = YES;
  238. self.volumeBrightnessView.hidden = YES;
  239. self.portraitControlView.hidden = self.player.isFullScreen;
  240. self.landScapeControlView.hidden = !self.player.isFullScreen;
  241. if (self.controlViewAppeared) {
  242. [self showControlViewWithAnimated:NO];
  243. } else {
  244. [self hideControlViewWithAnimated:NO];
  245. }
  246. }
  247. /// 设置标题、封面、全屏模式
  248. - (void)showTitle:(NSString *)title coverURLString:(NSString *)coverUrl fullScreenMode:(ZFFullScreenMode)fullScreenMode {
  249. UIImage *placeholder = [ZFUtilities imageWithColor:[UIColor colorWithRed:220/255.0 green:220/255.0 blue:220/255.0 alpha:1] size:self.bgImgView.bounds.size];
  250. [self showTitle:title coverURLString:coverUrl placeholderImage:placeholder fullScreenMode:fullScreenMode];
  251. }
  252. /// 设置标题、封面、默认占位图、全屏模式
  253. - (void)showTitle:(NSString *)title coverURLString:(NSString *)coverUrl placeholderImage:(UIImage *)placeholder fullScreenMode:(ZFFullScreenMode)fullScreenMode {
  254. [self resetControlView];
  255. [self layoutIfNeeded];
  256. [self setNeedsDisplay];
  257. [self.portraitControlView showTitle:title fullScreenMode:fullScreenMode];
  258. [self.landScapeControlView showTitle:title fullScreenMode:fullScreenMode];
  259. /// 这里直接设置播放器视图里的coverImageView
  260. [self.player.currentPlayerManager.view.coverImageView setImageWithURLString:coverUrl placeholder:placeholder];
  261. [self.bgImgView setImageWithURLString:coverUrl placeholder:placeholder];
  262. if (self.prepareShowControlView) {
  263. [self showControlViewWithAnimated:NO];
  264. } else {
  265. [self hideControlViewWithAnimated:NO];
  266. }
  267. }
  268. /// 设置标题、UIImage封面、全屏模式
  269. - (void)showTitle:(NSString *)title coverImage:(UIImage *)image fullScreenMode:(ZFFullScreenMode)fullScreenMode {
  270. [self resetControlView];
  271. [self layoutIfNeeded];
  272. [self setNeedsDisplay];
  273. [self.portraitControlView showTitle:title fullScreenMode:fullScreenMode];
  274. [self.landScapeControlView showTitle:title fullScreenMode:fullScreenMode];
  275. self.coverImageView.image = image;
  276. self.bgImgView.image = image;
  277. if (self.prepareShowControlView) {
  278. [self showControlViewWithAnimated:NO];
  279. } else {
  280. [self hideControlViewWithAnimated:NO];
  281. }
  282. }
  283. #pragma mark - ZFPlayerControlViewDelegate
  284. /// 手势筛选,返回NO不响应该手势
  285. - (BOOL)gestureTriggerCondition:(ZFPlayerGestureControl *)gestureControl gestureType:(ZFPlayerGestureType)gestureType gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer touch:(nonnull UITouch *)touch {
  286. CGPoint point = [touch locationInView:self];
  287. if (self.player.isSmallFloatViewShow && !self.player.isFullScreen && gestureType != ZFPlayerGestureTypeSingleTap) {
  288. return NO;
  289. }
  290. if (self.player.isFullScreen) {
  291. if (!self.customDisablePanMovingDirection) {
  292. /// 不禁用滑动方向
  293. self.player.disablePanMovingDirection = ZFPlayerDisablePanMovingDirectionNone;
  294. }
  295. return [self.landScapeControlView shouldResponseGestureWithPoint:point withGestureType:gestureType touch:touch];
  296. } else {
  297. if (!self.customDisablePanMovingDirection) {
  298. if (self.player.scrollView) { /// 列表时候禁止上下滑动(防止和列表滑动冲突)
  299. self.player.disablePanMovingDirection = ZFPlayerDisablePanMovingDirectionVertical;
  300. } else { /// 不禁用滑动方向
  301. self.player.disablePanMovingDirection = ZFPlayerDisablePanMovingDirectionNone;
  302. }
  303. }
  304. return [self.portraitControlView shouldResponseGestureWithPoint:point withGestureType:gestureType touch:touch];
  305. }
  306. }
  307. /// 单击手势事件
  308. - (void)gestureSingleTapped:(ZFPlayerGestureControl *)gestureControl {
  309. if (!self.player) return;
  310. if (self.player.isSmallFloatViewShow && !self.player.isFullScreen) {
  311. [self.player enterFullScreen:YES animated:YES];
  312. } else {
  313. if (self.controlViewAppeared) {
  314. [self hideControlViewWithAnimated:YES];
  315. } else {
  316. /// 显示之前先把控制层复位,先隐藏后显示
  317. [self hideControlViewWithAnimated:NO];
  318. [self showControlViewWithAnimated:YES];
  319. }
  320. }
  321. }
  322. /// 双击手势事件
  323. - (void)gestureDoubleTapped:(ZFPlayerGestureControl *)gestureControl {
  324. if (self.player.isFullScreen) {
  325. [self.landScapeControlView playOrPause];
  326. } else {
  327. [self.portraitControlView playOrPause];
  328. }
  329. }
  330. /// 开始滑动手势事件
  331. - (void)gestureBeganPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location {
  332. if (direction == ZFPanDirectionH) {
  333. self.sumTime = self.player.currentTime;
  334. }
  335. }
  336. /// 滑动中手势事件
  337. - (void)gestureChangedPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location withVelocity:(CGPoint)velocity {
  338. if (direction == ZFPanDirectionH) {
  339. // 每次滑动需要叠加时间
  340. self.sumTime += velocity.x / 200;
  341. // 需要限定sumTime的范围
  342. NSTimeInterval totalMovieDuration = self.player.totalTime;
  343. if (totalMovieDuration == 0) return;
  344. if (self.sumTime > totalMovieDuration) self.sumTime = totalMovieDuration;
  345. if (self.sumTime < 0) self.sumTime = 0;
  346. BOOL style = NO;
  347. if (velocity.x > 0) style = YES;
  348. if (velocity.x < 0) style = NO;
  349. if (velocity.x == 0) return;
  350. [self sliderValueChangingValue:self.sumTime/totalMovieDuration isForward:style];
  351. } else if (direction == ZFPanDirectionV) {
  352. if (location == ZFPanLocationLeft) { /// 调节亮度
  353. self.player.brightness -= (velocity.y) / 10000;
  354. [self.volumeBrightnessView updateProgress:self.player.brightness withVolumeBrightnessType:ZFVolumeBrightnessTypeumeBrightness];
  355. } else if (location == ZFPanLocationRight) { /// 调节声音
  356. self.player.volume -= (velocity.y) / 10000;
  357. if (self.player.isFullScreen) {
  358. [self.volumeBrightnessView updateProgress:self.player.volume withVolumeBrightnessType:ZFVolumeBrightnessTypeVolume];
  359. }
  360. }
  361. }
  362. }
  363. /// 滑动结束手势事件
  364. - (void)gestureEndedPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location {
  365. @weakify(self)
  366. if (direction == ZFPanDirectionH && self.sumTime >= 0 && self.player.totalTime > 0) {
  367. [self.player seekToTime:self.sumTime completionHandler:^(BOOL finished) {
  368. if (finished) {
  369. @strongify(self)
  370. /// 左右滑动调节播放进度
  371. [self.portraitControlView sliderChangeEnded];
  372. [self.landScapeControlView sliderChangeEnded];
  373. self.bottomPgrogress.isdragging = NO;
  374. if (self.controlViewAppeared) {
  375. [self autoFadeOutControlView];
  376. }
  377. }
  378. }];
  379. if (self.seekToPlay) {
  380. [self.player.currentPlayerManager play];
  381. }
  382. self.sumTime = 0;
  383. }
  384. }
  385. /// 捏合手势事件,这里改变了视频的填充模式
  386. - (void)gesturePinched:(ZFPlayerGestureControl *)gestureControl scale:(float)scale {
  387. if (scale > 1) {
  388. self.player.currentPlayerManager.scalingMode = ZFPlayerScalingModeAspectFill;
  389. } else {
  390. self.player.currentPlayerManager.scalingMode = ZFPlayerScalingModeAspectFit;
  391. }
  392. }
  393. /// 准备播放
  394. - (void)videoPlayer:(ZFPlayerController *)videoPlayer prepareToPlay:(NSURL *)assetURL {
  395. [self hideControlViewWithAnimated:NO];
  396. }
  397. /// 播放状态改变
  398. - (void)videoPlayer:(ZFPlayerController *)videoPlayer playStateChanged:(ZFPlayerPlaybackState)state {
  399. if (state == ZFPlayerPlayStatePlaying) {
  400. [self.portraitControlView playBtnSelectedState:YES];
  401. [self.landScapeControlView playBtnSelectedState:YES];
  402. self.failBtn.hidden = YES;
  403. /// 开始播放时候判断是否显示loading
  404. if (videoPlayer.currentPlayerManager.loadState == ZFPlayerLoadStateStalled && !self.prepareShowLoading) {
  405. [self.activity startAnimating];
  406. } else if ((videoPlayer.currentPlayerManager.loadState == ZFPlayerLoadStateStalled || videoPlayer.currentPlayerManager.loadState == ZFPlayerLoadStatePrepare) && self.prepareShowLoading) {
  407. [self.activity startAnimating];
  408. }
  409. } else if (state == ZFPlayerPlayStatePaused) {
  410. [self.portraitControlView playBtnSelectedState:NO];
  411. [self.landScapeControlView playBtnSelectedState:NO];
  412. /// 暂停的时候隐藏loading
  413. [self.activity stopAnimating];
  414. self.failBtn.hidden = YES;
  415. } else if (state == ZFPlayerPlayStatePlayFailed) {
  416. self.failBtn.hidden = NO;
  417. [self.activity stopAnimating];
  418. }
  419. }
  420. /// 加载状态改变
  421. - (void)videoPlayer:(ZFPlayerController *)videoPlayer loadStateChanged:(ZFPlayerLoadState)state {
  422. if (state == ZFPlayerLoadStatePrepare) {
  423. self.coverImageView.hidden = NO;
  424. [self.portraitControlView playBtnSelectedState:videoPlayer.currentPlayerManager.shouldAutoPlay];
  425. [self.landScapeControlView playBtnSelectedState:videoPlayer.currentPlayerManager.shouldAutoPlay];
  426. } else if (state == ZFPlayerLoadStatePlaythroughOK || state == ZFPlayerLoadStatePlayable) {
  427. self.coverImageView.hidden = YES;
  428. if (self.effectViewShow) {
  429. self.effectView.hidden = NO;
  430. } else {
  431. self.effectView.hidden = YES;
  432. self.player.currentPlayerManager.view.backgroundColor = [UIColor blackColor];
  433. }
  434. }
  435. if (state == ZFPlayerLoadStateStalled && videoPlayer.currentPlayerManager.isPlaying && !self.prepareShowLoading) {
  436. [self.activity startAnimating];
  437. } else if ((state == ZFPlayerLoadStateStalled || state == ZFPlayerLoadStatePrepare) && videoPlayer.currentPlayerManager.isPlaying && self.prepareShowLoading) {
  438. [self.activity startAnimating];
  439. } else {
  440. [self.activity stopAnimating];
  441. }
  442. }
  443. /// 播放进度改变回调
  444. - (void)videoPlayer:(ZFPlayerController *)videoPlayer currentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime {
  445. [self.portraitControlView videoPlayer:videoPlayer currentTime:currentTime totalTime:totalTime];
  446. [self.landScapeControlView videoPlayer:videoPlayer currentTime:currentTime totalTime:totalTime];
  447. if (!self.bottomPgrogress.isdragging) {
  448. self.bottomPgrogress.value = videoPlayer.progress;
  449. }
  450. }
  451. /// 缓冲改变回调
  452. - (void)videoPlayer:(ZFPlayerController *)videoPlayer bufferTime:(NSTimeInterval)bufferTime {
  453. [self.portraitControlView videoPlayer:videoPlayer bufferTime:bufferTime];
  454. [self.landScapeControlView videoPlayer:videoPlayer bufferTime:bufferTime];
  455. self.bottomPgrogress.bufferValue = videoPlayer.bufferProgress;
  456. }
  457. - (void)videoPlayer:(ZFPlayerController *)videoPlayer presentationSizeChanged:(CGSize)size {
  458. [self.landScapeControlView videoPlayer:videoPlayer presentationSizeChanged:size];
  459. }
  460. /// 视频view即将旋转
  461. - (void)videoPlayer:(ZFPlayerController *)videoPlayer orientationWillChange:(ZFOrientationObserver *)observer {
  462. self.portraitControlView.hidden = observer.isFullScreen;
  463. self.landScapeControlView.hidden = !observer.isFullScreen;
  464. if (videoPlayer.isSmallFloatViewShow) {
  465. self.floatControlView.hidden = observer.isFullScreen;
  466. self.portraitControlView.hidden = YES;
  467. if (observer.isFullScreen) {
  468. self.controlViewAppeared = NO;
  469. [self cancelAutoFadeOutControlView];
  470. }
  471. }
  472. if (self.controlViewAppeared) {
  473. [self showControlViewWithAnimated:NO];
  474. } else {
  475. [self hideControlViewWithAnimated:NO];
  476. }
  477. if (observer.isFullScreen) {
  478. [self.volumeBrightnessView removeSystemVolumeView];
  479. } else {
  480. [self.volumeBrightnessView addSystemVolumeView];
  481. }
  482. }
  483. /// 视频view已经旋转
  484. - (void)videoPlayer:(ZFPlayerController *)videoPlayer orientationDidChanged:(ZFOrientationObserver *)observer {
  485. if (self.controlViewAppeared) {
  486. [self showControlViewWithAnimated:NO];
  487. } else {
  488. [self hideControlViewWithAnimated:NO];
  489. }
  490. }
  491. /// 锁定旋转方向
  492. - (void)lockedVideoPlayer:(ZFPlayerController *)videoPlayer lockedScreen:(BOOL)locked {
  493. [self showControlViewWithAnimated:YES];
  494. }
  495. /// 列表滑动时视频view已经显示
  496. - (void)playerDidAppearInScrollView:(ZFPlayerController *)videoPlayer {
  497. if (!self.player.stopWhileNotVisible && !videoPlayer.isFullScreen) {
  498. self.floatControlView.hidden = YES;
  499. self.portraitControlView.hidden = NO;
  500. }
  501. }
  502. /// 列表滑动时视频view已经消失
  503. - (void)playerDidDisappearInScrollView:(ZFPlayerController *)videoPlayer {
  504. if (!self.player.stopWhileNotVisible && !videoPlayer.isFullScreen) {
  505. self.floatControlView.hidden = NO;
  506. self.portraitControlView.hidden = YES;
  507. }
  508. }
  509. - (void)videoPlayer:(ZFPlayerController *)videoPlayer floatViewShow:(BOOL)show {
  510. self.floatControlView.hidden = !show;
  511. self.portraitControlView.hidden = show;
  512. }
  513. #pragma mark - Private Method
  514. - (void)sliderValueChangingValue:(CGFloat)value isForward:(BOOL)forward {
  515. if (self.horizontalPanShowControlView) {
  516. /// 显示控制层
  517. [self showControlViewWithAnimated:NO];
  518. [self cancelAutoFadeOutControlView];
  519. }
  520. self.fastProgressView.value = value;
  521. self.fastView.hidden = NO;
  522. self.fastView.alpha = 1;
  523. if (forward) {
  524. self.fastImageView.image = ZFPlayer_Image(@"ZFPlayer_fast_forward");
  525. } else {
  526. self.fastImageView.image = ZFPlayer_Image(@"ZFPlayer_fast_backward");
  527. }
  528. NSString *draggedTime = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
  529. NSString *totalTime = [ZFUtilities convertTimeSecond:self.player.totalTime];
  530. self.fastTimeLabel.text = [NSString stringWithFormat:@"%@ / %@",draggedTime,totalTime];
  531. /// 更新滑杆
  532. [self.portraitControlView sliderValueChanged:value currentTimeString:draggedTime];
  533. [self.landScapeControlView sliderValueChanged:value currentTimeString:draggedTime];
  534. self.bottomPgrogress.isdragging = YES;
  535. self.bottomPgrogress.value = value;
  536. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideFastView) object:nil];
  537. [self performSelector:@selector(hideFastView) withObject:nil afterDelay:0.1];
  538. if (self.fastViewAnimated) {
  539. [UIView animateWithDuration:0.4 animations:^{
  540. self.fastView.transform = CGAffineTransformMakeTranslation(forward?8:-8, 0);
  541. }];
  542. }
  543. }
  544. /// 隐藏快进视图
  545. - (void)hideFastView {
  546. [UIView animateWithDuration:0.4 animations:^{
  547. self.fastView.transform = CGAffineTransformIdentity;
  548. self.fastView.alpha = 0;
  549. } completion:^(BOOL finished) {
  550. self.fastView.hidden = YES;
  551. }];
  552. }
  553. /// 加载失败
  554. - (void)failBtnClick:(UIButton *)sender {
  555. [self.player.currentPlayerManager reloadPlayer];
  556. }
  557. #pragma mark - setter
  558. - (void)setPlayer:(ZFPlayerController *)player {
  559. _player = player;
  560. self.landScapeControlView.player = player;
  561. self.portraitControlView.player = player;
  562. /// 解决播放时候黑屏闪一下问题
  563. [player.currentPlayerManager.view insertSubview:self.bgImgView atIndex:0];
  564. [self.bgImgView addSubview:self.effectView];
  565. self.bgImgView.frame = player.currentPlayerManager.view.bounds;
  566. self.bgImgView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  567. self.effectView.frame = self.bgImgView.bounds;
  568. }
  569. - (void)setSeekToPlay:(BOOL)seekToPlay {
  570. _seekToPlay = seekToPlay;
  571. self.portraitControlView.seekToPlay = seekToPlay;
  572. self.landScapeControlView.seekToPlay = seekToPlay;
  573. }
  574. - (void)setEffectViewShow:(BOOL)effectViewShow {
  575. _effectViewShow = effectViewShow;
  576. if (effectViewShow) {
  577. self.bgImgView.hidden = NO;
  578. } else {
  579. self.bgImgView.hidden = YES;
  580. }
  581. }
  582. - (void)setFullScreenMode:(ZFFullScreenMode)fullScreenMode {
  583. _fullScreenMode = fullScreenMode;
  584. self.portraitControlView.fullScreenMode = fullScreenMode;
  585. self.landScapeControlView.fullScreenMode = fullScreenMode;
  586. self.player.orientationObserver.fullScreenMode = fullScreenMode;
  587. }
  588. #pragma mark - getter
  589. - (UIImageView *)bgImgView {
  590. if (!_bgImgView) {
  591. _bgImgView = [[UIImageView alloc] init];
  592. _bgImgView.userInteractionEnabled = YES;
  593. }
  594. return _bgImgView;
  595. }
  596. - (UIView *)effectView {
  597. if (!_effectView) {
  598. if (@available(iOS 8.0, *)) {
  599. UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
  600. _effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
  601. } else {
  602. UIToolbar *effectView = [[UIToolbar alloc] init];
  603. effectView.barStyle = UIBarStyleBlackTranslucent;
  604. _effectView = effectView;
  605. }
  606. }
  607. return _effectView;
  608. }
  609. - (ZFPortraitControlView *)portraitControlView {
  610. if (!_portraitControlView) {
  611. @weakify(self)
  612. _portraitControlView = [[ZFPortraitControlView alloc] init];
  613. _portraitControlView.sliderValueChanging = ^(CGFloat value, BOOL forward) {
  614. @strongify(self)
  615. NSString *draggedTime = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
  616. /// 更新滑杆和时间
  617. [self.landScapeControlView sliderValueChanged:value currentTimeString:draggedTime];
  618. self.fastProgressView.value = value;
  619. self.bottomPgrogress.isdragging = YES;
  620. self.bottomPgrogress.value = value;
  621. [self cancelAutoFadeOutControlView];
  622. };
  623. _portraitControlView.sliderValueChanged = ^(CGFloat value) {
  624. @strongify(self)
  625. [self.landScapeControlView sliderChangeEnded];
  626. self.fastProgressView.value = value;
  627. self.bottomPgrogress.isdragging = NO;
  628. self.bottomPgrogress.value = value;
  629. [self autoFadeOutControlView];
  630. };
  631. }
  632. return _portraitControlView;
  633. }
  634. - (ZFLandScapeControlView *)landScapeControlView {
  635. if (!_landScapeControlView) {
  636. @weakify(self)
  637. _landScapeControlView = [[ZFLandScapeControlView alloc] init];
  638. _landScapeControlView.sliderValueChanging = ^(CGFloat value, BOOL forward) {
  639. @strongify(self)
  640. NSString *draggedTime = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
  641. /// 更新滑杆和时间
  642. [self.portraitControlView sliderValueChanged:value currentTimeString:draggedTime];
  643. self.fastProgressView.value = value;
  644. self.bottomPgrogress.isdragging = YES;
  645. self.bottomPgrogress.value = value;
  646. [self cancelAutoFadeOutControlView];
  647. };
  648. _landScapeControlView.sliderValueChanged = ^(CGFloat value) {
  649. @strongify(self)
  650. [self.portraitControlView sliderChangeEnded];
  651. self.fastProgressView.value = value;
  652. self.bottomPgrogress.isdragging = NO;
  653. self.bottomPgrogress.value = value;
  654. [self autoFadeOutControlView];
  655. };
  656. }
  657. return _landScapeControlView;
  658. }
  659. - (ZFSpeedLoadingView *)activity {
  660. if (!_activity) {
  661. _activity = [[ZFSpeedLoadingView alloc] init];
  662. }
  663. return _activity;
  664. }
  665. - (UIView *)fastView {
  666. if (!_fastView) {
  667. _fastView = [[UIView alloc] init];
  668. _fastView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
  669. _fastView.layer.cornerRadius = 4;
  670. _fastView.layer.masksToBounds = YES;
  671. _fastView.hidden = YES;
  672. }
  673. return _fastView;
  674. }
  675. - (UIImageView *)fastImageView {
  676. if (!_fastImageView) {
  677. _fastImageView = [[UIImageView alloc] init];
  678. }
  679. return _fastImageView;
  680. }
  681. - (UILabel *)fastTimeLabel {
  682. if (!_fastTimeLabel) {
  683. _fastTimeLabel = [[UILabel alloc] init];
  684. _fastTimeLabel.textColor = [UIColor whiteColor];
  685. _fastTimeLabel.textAlignment = NSTextAlignmentCenter;
  686. _fastTimeLabel.font = [UIFont systemFontOfSize:14.0];
  687. _fastTimeLabel.adjustsFontSizeToFitWidth = YES;
  688. }
  689. return _fastTimeLabel;
  690. }
  691. - (ZFSliderView *)fastProgressView {
  692. if (!_fastProgressView) {
  693. _fastProgressView = [[ZFSliderView alloc] init];
  694. _fastProgressView.maximumTrackTintColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.4];
  695. _fastProgressView.minimumTrackTintColor = [UIColor whiteColor];
  696. _fastProgressView.sliderHeight = 2;
  697. _fastProgressView.isHideSliderBlock = NO;
  698. }
  699. return _fastProgressView;
  700. }
  701. - (UIButton *)failBtn {
  702. if (!_failBtn) {
  703. _failBtn = [UIButton buttonWithType:UIButtonTypeSystem];
  704. [_failBtn setTitle:@"Loading Failed, Click Retry" forState:UIControlStateNormal];
  705. [_failBtn addTarget:self action:@selector(failBtnClick:) forControlEvents:UIControlEventTouchUpInside];
  706. [_failBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  707. _failBtn.titleLabel.font = [UIFont systemFontOfSize:14.0];
  708. _failBtn.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
  709. _failBtn.hidden = YES;
  710. }
  711. return _failBtn;
  712. }
  713. - (ZFSliderView *)bottomPgrogress {
  714. if (!_bottomPgrogress) {
  715. _bottomPgrogress = [[ZFSliderView alloc] init];
  716. _bottomPgrogress.maximumTrackTintColor = [UIColor clearColor];
  717. _bottomPgrogress.minimumTrackTintColor = [UIColor whiteColor];
  718. _bottomPgrogress.bufferTrackTintColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.5];
  719. _bottomPgrogress.sliderHeight = 1;
  720. _bottomPgrogress.isHideSliderBlock = NO;
  721. }
  722. return _bottomPgrogress;
  723. }
  724. - (ZFSmallFloatControlView *)floatControlView {
  725. if (!_floatControlView) {
  726. _floatControlView = [[ZFSmallFloatControlView alloc] init];
  727. @weakify(self)
  728. _floatControlView.closeClickCallback = ^{
  729. @strongify(self)
  730. if (self.player.containerType == ZFPlayerContainerTypeCell) {
  731. [self.player stopCurrentPlayingCell];
  732. } else if (self.player.containerType == ZFPlayerContainerTypeView) {
  733. [self.player stopCurrentPlayingView];
  734. }
  735. [self resetControlView];
  736. };
  737. }
  738. return _floatControlView;
  739. }
  740. - (ZFVolumeBrightnessView *)volumeBrightnessView {
  741. if (!_volumeBrightnessView) {
  742. _volumeBrightnessView = [[ZFVolumeBrightnessView alloc] init];
  743. _volumeBrightnessView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
  744. _volumeBrightnessView.hidden = YES;
  745. }
  746. return _volumeBrightnessView;
  747. }
  748. - (void)setBackBtnClickCallback:(void (^)(void))backBtnClickCallback {
  749. _backBtnClickCallback = [backBtnClickCallback copy];
  750. self.landScapeControlView.backBtnClickCallback = _backBtnClickCallback;
  751. }
  752. @end