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. @zf_weakify(self)
  165. self.afterBlock = dispatch_block_create(0, ^{
  166. @zf_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. [self showControlViewWithAnimated:YES];
  317. }
  318. }
  319. }
  320. /// 双击手势事件
  321. - (void)gestureDoubleTapped:(ZFPlayerGestureControl *)gestureControl {
  322. if (self.player.isFullScreen) {
  323. [self.landScapeControlView playOrPause];
  324. } else {
  325. [self.portraitControlView playOrPause];
  326. }
  327. }
  328. /// 开始滑动手势事件
  329. - (void)gestureBeganPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location {
  330. if (direction == ZFPanDirectionH) {
  331. self.sumTime = self.player.currentTime;
  332. }
  333. }
  334. /// 滑动中手势事件
  335. - (void)gestureChangedPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location withVelocity:(CGPoint)velocity {
  336. if (direction == ZFPanDirectionH) {
  337. // 每次滑动需要叠加时间
  338. self.sumTime += velocity.x / 200;
  339. // 需要限定sumTime的范围
  340. NSTimeInterval totalMovieDuration = self.player.totalTime;
  341. if (totalMovieDuration == 0) return;
  342. if (self.sumTime > totalMovieDuration) self.sumTime = totalMovieDuration;
  343. if (self.sumTime < 0) self.sumTime = 0;
  344. BOOL style = NO;
  345. if (velocity.x > 0) style = YES;
  346. if (velocity.x < 0) style = NO;
  347. if (velocity.x == 0) return;
  348. [self sliderValueChangingValue:self.sumTime/totalMovieDuration isForward:style];
  349. } else if (direction == ZFPanDirectionV) {
  350. if (location == ZFPanLocationLeft) { /// 调节亮度
  351. self.player.brightness -= (velocity.y) / 10000;
  352. [self.volumeBrightnessView updateProgress:self.player.brightness withVolumeBrightnessType:ZFVolumeBrightnessTypeumeBrightness];
  353. } else if (location == ZFPanLocationRight) { /// 调节声音
  354. self.player.volume -= (velocity.y) / 10000;
  355. if (self.player.isFullScreen) {
  356. [self.volumeBrightnessView updateProgress:self.player.volume withVolumeBrightnessType:ZFVolumeBrightnessTypeVolume];
  357. }
  358. }
  359. }
  360. }
  361. /// 滑动结束手势事件
  362. - (void)gestureEndedPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location {
  363. @zf_weakify(self)
  364. if (direction == ZFPanDirectionH && self.sumTime >= 0 && self.player.totalTime > 0) {
  365. [self.player seekToTime:self.sumTime completionHandler:^(BOOL finished) {
  366. if (finished) {
  367. @zf_strongify(self)
  368. /// 左右滑动调节播放进度
  369. [self.portraitControlView sliderChangeEnded];
  370. [self.landScapeControlView sliderChangeEnded];
  371. self.bottomPgrogress.isdragging = NO;
  372. if (self.controlViewAppeared) {
  373. [self autoFadeOutControlView];
  374. }
  375. }
  376. }];
  377. if (self.seekToPlay) {
  378. [self.player.currentPlayerManager play];
  379. }
  380. self.sumTime = 0;
  381. }
  382. }
  383. /// 捏合手势事件,这里改变了视频的填充模式
  384. - (void)gesturePinched:(ZFPlayerGestureControl *)gestureControl scale:(float)scale {
  385. if (scale > 1) {
  386. self.player.currentPlayerManager.scalingMode = ZFPlayerScalingModeAspectFill;
  387. } else {
  388. self.player.currentPlayerManager.scalingMode = ZFPlayerScalingModeAspectFit;
  389. }
  390. }
  391. - (void)longPressed:(ZFPlayerGestureControl *)gestureControl state:(ZFLongPressGestureRecognizerState)state {
  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. [self.landScapeControlView videoPlayer:videoPlayer orientationWillChange:observer];
  483. }
  484. /// 锁定旋转方向
  485. - (void)lockedVideoPlayer:(ZFPlayerController *)videoPlayer lockedScreen:(BOOL)locked {
  486. [self showControlViewWithAnimated:YES];
  487. }
  488. /// 列表滑动时视频view已经显示
  489. - (void)playerDidAppearInScrollView:(ZFPlayerController *)videoPlayer {
  490. if (!self.player.stopWhileNotVisible && !videoPlayer.isFullScreen) {
  491. self.floatControlView.hidden = YES;
  492. self.portraitControlView.hidden = NO;
  493. }
  494. }
  495. /// 列表滑动时视频view已经消失
  496. - (void)playerDidDisappearInScrollView:(ZFPlayerController *)videoPlayer {
  497. if (!self.player.stopWhileNotVisible && !videoPlayer.isFullScreen) {
  498. self.floatControlView.hidden = NO;
  499. self.portraitControlView.hidden = YES;
  500. }
  501. }
  502. - (void)videoPlayer:(ZFPlayerController *)videoPlayer floatViewShow:(BOOL)show {
  503. self.floatControlView.hidden = !show;
  504. self.portraitControlView.hidden = show;
  505. }
  506. #pragma mark - Private Method
  507. - (void)sliderValueChangingValue:(CGFloat)value isForward:(BOOL)forward {
  508. if (self.horizontalPanShowControlView) {
  509. /// 显示控制层
  510. [self showControlViewWithAnimated:NO];
  511. [self cancelAutoFadeOutControlView];
  512. }
  513. self.fastProgressView.value = value;
  514. self.fastView.hidden = NO;
  515. self.fastView.alpha = 1;
  516. if (forward) {
  517. self.fastImageView.image = ZFPlayer_Image(@"ZFPlayer_fast_forward");
  518. } else {
  519. self.fastImageView.image = ZFPlayer_Image(@"ZFPlayer_fast_backward");
  520. }
  521. NSString *draggedTime = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
  522. NSString *totalTime = [ZFUtilities convertTimeSecond:self.player.totalTime];
  523. self.fastTimeLabel.text = [NSString stringWithFormat:@"%@ / %@",draggedTime,totalTime];
  524. /// 更新滑杆
  525. [self.portraitControlView sliderValueChanged:value currentTimeString:draggedTime];
  526. [self.landScapeControlView sliderValueChanged:value currentTimeString:draggedTime];
  527. self.bottomPgrogress.isdragging = YES;
  528. self.bottomPgrogress.value = value;
  529. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideFastView) object:nil];
  530. [self performSelector:@selector(hideFastView) withObject:nil afterDelay:0.1];
  531. if (self.fastViewAnimated) {
  532. [UIView animateWithDuration:0.4 animations:^{
  533. self.fastView.transform = CGAffineTransformMakeTranslation(forward?8:-8, 0);
  534. }];
  535. }
  536. }
  537. /// 隐藏快进视图
  538. - (void)hideFastView {
  539. [UIView animateWithDuration:0.4 animations:^{
  540. self.fastView.transform = CGAffineTransformIdentity;
  541. self.fastView.alpha = 0;
  542. } completion:^(BOOL finished) {
  543. self.fastView.hidden = YES;
  544. }];
  545. }
  546. /// 加载失败
  547. - (void)failBtnClick:(UIButton *)sender {
  548. [self.player.currentPlayerManager reloadPlayer];
  549. }
  550. #pragma mark - setter
  551. - (void)setPlayer:(ZFPlayerController *)player {
  552. _player = player;
  553. self.landScapeControlView.player = player;
  554. self.portraitControlView.player = player;
  555. /// 解决播放时候黑屏闪一下问题
  556. [player.currentPlayerManager.view insertSubview:self.bgImgView atIndex:0];
  557. [self.bgImgView addSubview:self.effectView];
  558. self.bgImgView.frame = player.currentPlayerManager.view.bounds;
  559. self.bgImgView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  560. self.effectView.frame = self.bgImgView.bounds;
  561. }
  562. - (void)setSeekToPlay:(BOOL)seekToPlay {
  563. _seekToPlay = seekToPlay;
  564. self.portraitControlView.seekToPlay = seekToPlay;
  565. self.landScapeControlView.seekToPlay = seekToPlay;
  566. }
  567. - (void)setEffectViewShow:(BOOL)effectViewShow {
  568. _effectViewShow = effectViewShow;
  569. if (effectViewShow) {
  570. self.bgImgView.hidden = NO;
  571. } else {
  572. self.bgImgView.hidden = YES;
  573. }
  574. }
  575. - (void)setFullScreenMode:(ZFFullScreenMode)fullScreenMode {
  576. _fullScreenMode = fullScreenMode;
  577. self.portraitControlView.fullScreenMode = fullScreenMode;
  578. self.landScapeControlView.fullScreenMode = fullScreenMode;
  579. self.player.orientationObserver.fullScreenMode = fullScreenMode;
  580. }
  581. - (void)setShowCustomStatusBar:(BOOL)showCustomStatusBar {
  582. _showCustomStatusBar = showCustomStatusBar;
  583. self.landScapeControlView.showCustomStatusBar = showCustomStatusBar;
  584. }
  585. #pragma mark - getter
  586. - (UIImageView *)bgImgView {
  587. if (!_bgImgView) {
  588. _bgImgView = [[UIImageView alloc] init];
  589. _bgImgView.userInteractionEnabled = YES;
  590. }
  591. return _bgImgView;
  592. }
  593. - (UIView *)effectView {
  594. if (!_effectView) {
  595. if (@available(iOS 8.0, *)) {
  596. UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
  597. _effectView = [[UIVisualEffectView alloc] initWithEffect:effect];
  598. } else {
  599. UIToolbar *effectView = [[UIToolbar alloc] init];
  600. effectView.barStyle = UIBarStyleBlackTranslucent;
  601. _effectView = effectView;
  602. }
  603. }
  604. return _effectView;
  605. }
  606. - (ZFPortraitControlView *)portraitControlView {
  607. if (!_portraitControlView) {
  608. @zf_weakify(self)
  609. _portraitControlView = [[ZFPortraitControlView alloc] init];
  610. _portraitControlView.sliderValueChanging = ^(CGFloat value, BOOL forward) {
  611. @zf_strongify(self)
  612. NSString *draggedTime = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
  613. /// 更新滑杆和时间
  614. [self.landScapeControlView sliderValueChanged:value currentTimeString:draggedTime];
  615. self.fastProgressView.value = value;
  616. self.bottomPgrogress.isdragging = YES;
  617. self.bottomPgrogress.value = value;
  618. [self cancelAutoFadeOutControlView];
  619. };
  620. _portraitControlView.sliderValueChanged = ^(CGFloat value) {
  621. @zf_strongify(self)
  622. [self.landScapeControlView sliderChangeEnded];
  623. self.fastProgressView.value = value;
  624. self.bottomPgrogress.isdragging = NO;
  625. self.bottomPgrogress.value = value;
  626. [self autoFadeOutControlView];
  627. };
  628. }
  629. return _portraitControlView;
  630. }
  631. - (ZFLandScapeControlView *)landScapeControlView {
  632. if (!_landScapeControlView) {
  633. @zf_weakify(self)
  634. _landScapeControlView = [[ZFLandScapeControlView alloc] init];
  635. _landScapeControlView.sliderValueChanging = ^(CGFloat value, BOOL forward) {
  636. @zf_strongify(self)
  637. NSString *draggedTime = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
  638. /// 更新滑杆和时间
  639. [self.portraitControlView sliderValueChanged:value currentTimeString:draggedTime];
  640. self.fastProgressView.value = value;
  641. self.bottomPgrogress.isdragging = YES;
  642. self.bottomPgrogress.value = value;
  643. [self cancelAutoFadeOutControlView];
  644. };
  645. _landScapeControlView.sliderValueChanged = ^(CGFloat value) {
  646. @zf_strongify(self)
  647. [self.portraitControlView sliderChangeEnded];
  648. self.fastProgressView.value = value;
  649. self.bottomPgrogress.isdragging = NO;
  650. self.bottomPgrogress.value = value;
  651. [self autoFadeOutControlView];
  652. };
  653. }
  654. return _landScapeControlView;
  655. }
  656. - (ZFSpeedLoadingView *)activity {
  657. if (!_activity) {
  658. _activity = [[ZFSpeedLoadingView alloc] init];
  659. }
  660. return _activity;
  661. }
  662. - (UIView *)fastView {
  663. if (!_fastView) {
  664. _fastView = [[UIView alloc] init];
  665. _fastView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
  666. _fastView.layer.cornerRadius = 4;
  667. _fastView.layer.masksToBounds = YES;
  668. _fastView.hidden = YES;
  669. }
  670. return _fastView;
  671. }
  672. - (UIImageView *)fastImageView {
  673. if (!_fastImageView) {
  674. _fastImageView = [[UIImageView alloc] init];
  675. }
  676. return _fastImageView;
  677. }
  678. - (UILabel *)fastTimeLabel {
  679. if (!_fastTimeLabel) {
  680. _fastTimeLabel = [[UILabel alloc] init];
  681. _fastTimeLabel.textColor = [UIColor whiteColor];
  682. _fastTimeLabel.textAlignment = NSTextAlignmentCenter;
  683. _fastTimeLabel.font = [UIFont systemFontOfSize:14.0];
  684. _fastTimeLabel.adjustsFontSizeToFitWidth = YES;
  685. }
  686. return _fastTimeLabel;
  687. }
  688. - (ZFSliderView *)fastProgressView {
  689. if (!_fastProgressView) {
  690. _fastProgressView = [[ZFSliderView alloc] init];
  691. _fastProgressView.maximumTrackTintColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.4];
  692. _fastProgressView.minimumTrackTintColor = [UIColor whiteColor];
  693. _fastProgressView.sliderHeight = 2;
  694. _fastProgressView.isHideSliderBlock = NO;
  695. }
  696. return _fastProgressView;
  697. }
  698. - (UIButton *)failBtn {
  699. if (!_failBtn) {
  700. _failBtn = [UIButton buttonWithType:UIButtonTypeSystem];
  701. [_failBtn setTitle:@"加载失败,点击重试" forState:UIControlStateNormal];
  702. [_failBtn addTarget:self action:@selector(failBtnClick:) forControlEvents:UIControlEventTouchUpInside];
  703. [_failBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  704. _failBtn.titleLabel.font = [UIFont systemFontOfSize:14.0];
  705. _failBtn.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
  706. _failBtn.hidden = YES;
  707. }
  708. return _failBtn;
  709. }
  710. - (ZFSliderView *)bottomPgrogress {
  711. if (!_bottomPgrogress) {
  712. _bottomPgrogress = [[ZFSliderView alloc] init];
  713. _bottomPgrogress.maximumTrackTintColor = [UIColor clearColor];
  714. _bottomPgrogress.minimumTrackTintColor = [UIColor whiteColor];
  715. _bottomPgrogress.bufferTrackTintColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.5];
  716. _bottomPgrogress.sliderHeight = 1;
  717. _bottomPgrogress.isHideSliderBlock = NO;
  718. }
  719. return _bottomPgrogress;
  720. }
  721. - (ZFSmallFloatControlView *)floatControlView {
  722. if (!_floatControlView) {
  723. _floatControlView = [[ZFSmallFloatControlView alloc] init];
  724. @zf_weakify(self)
  725. _floatControlView.closeClickCallback = ^{
  726. @zf_strongify(self)
  727. if (self.player.containerType == ZFPlayerContainerTypeCell) {
  728. [self.player stopCurrentPlayingCell];
  729. } else if (self.player.containerType == ZFPlayerContainerTypeView) {
  730. [self.player stopCurrentPlayingView];
  731. }
  732. [self resetControlView];
  733. };
  734. }
  735. return _floatControlView;
  736. }
  737. - (ZFVolumeBrightnessView *)volumeBrightnessView {
  738. if (!_volumeBrightnessView) {
  739. _volumeBrightnessView = [[ZFVolumeBrightnessView alloc] init];
  740. _volumeBrightnessView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
  741. _volumeBrightnessView.hidden = YES;
  742. }
  743. return _volumeBrightnessView;
  744. }
  745. - (void)setBackBtnClickCallback:(void (^)(void))backBtnClickCallback {
  746. _backBtnClickCallback = [backBtnClickCallback copy];
  747. self.landScapeControlView.backBtnClickCallback = _backBtnClickCallback;
  748. }
  749. @end