ZFPlayerControlView.m 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  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/ZFPlayer.h>
  35. #else
  36. #import "ZFPlayer.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, strong) UIImageView *coverImageView;
  59. /// 是否显示了控制层
  60. @property (nonatomic, assign, getter=isShowing) BOOL showing;
  61. /// 是否播放结束
  62. @property (nonatomic, assign, getter=isPlayEnd) BOOL playeEnd;
  63. @property (nonatomic, assign) BOOL controlViewAppeared;
  64. @property (nonatomic, assign) NSTimeInterval sumTime;
  65. @property (nonatomic, strong) dispatch_block_t afterBlock;
  66. @property (nonatomic, strong) ZFSmallFloatControlView *floatControlView;
  67. @property (nonatomic, strong) ZFVolumeBrightnessView *volumeBrightnessView;
  68. @property (nonatomic, strong) UIImageView *bgImgView;
  69. @property (nonatomic, strong) UIView *effectView;
  70. @end
  71. @implementation ZFPlayerControlView
  72. @synthesize player = _player;
  73. - (instancetype)initWithFrame:(CGRect)frame {
  74. self = [super initWithFrame:frame];
  75. if (self) {
  76. [self addAllSubViews];
  77. self.landScapeControlView.hidden = YES;
  78. self.floatControlView.hidden = YES;
  79. self.seekToPlay = YES;
  80. self.effectViewShow = YES;
  81. self.horizontalPanShowControlView = YES;
  82. self.autoFadeTimeInterval = 0.25;
  83. self.autoHiddenTimeInterval = 2.5;
  84. [[NSNotificationCenter defaultCenter] addObserver:self
  85. selector:@selector(volumeChanged:)
  86. name:@"AVSystemController_SystemVolumeDidChangeNotification"
  87. object:nil];
  88. }
  89. return self;
  90. }
  91. - (void)layoutSubviews {
  92. [super layoutSubviews];
  93. CGFloat min_x = 0;
  94. CGFloat min_y = 0;
  95. CGFloat min_w = 0;
  96. CGFloat min_h = 0;
  97. CGFloat min_view_w = self.zf_width;
  98. CGFloat min_view_h = self.zf_height;
  99. self.portraitControlView.frame = self.bounds;
  100. self.landScapeControlView.frame = self.bounds;
  101. self.floatControlView.frame = self.bounds;
  102. self.coverImageView.frame = self.bounds;
  103. self.bgImgView.frame = self.bounds;
  104. self.effectView.frame = self.bounds;
  105. min_w = 80;
  106. min_h = 80;
  107. self.activity.frame = CGRectMake(min_x, min_y, min_w, min_h);
  108. self.activity.zf_centerX = self.zf_centerX;
  109. self.activity.zf_centerY = self.zf_centerY + 10;
  110. min_w = 150;
  111. min_h = 30;
  112. self.failBtn.frame = CGRectMake(min_x, min_y, min_w, min_h);
  113. self.failBtn.center = self.center;
  114. min_w = 140;
  115. min_h = 80;
  116. self.fastView.frame = CGRectMake(min_x, min_y, min_w, min_h);
  117. self.fastView.center = self.center;
  118. min_w = 32;
  119. min_x = (self.fastView.zf_width - min_w) / 2;
  120. min_y = 5;
  121. min_h = 32;
  122. self.fastImageView.frame = CGRectMake(min_x, min_y, min_w, min_h);
  123. min_x = 0;
  124. min_y = self.fastImageView.zf_bottom + 2;
  125. min_w = self.fastView.zf_width;
  126. min_h = 20;
  127. self.fastTimeLabel.frame = CGRectMake(min_x, min_y, min_w, min_h);
  128. min_x = 12;
  129. min_y = self.fastTimeLabel.zf_bottom + 5;
  130. min_w = self.fastView.zf_width - 2 * min_x;
  131. min_h = 10;
  132. self.fastProgressView.frame = CGRectMake(min_x, min_y, min_w, min_h);
  133. min_x = 0;
  134. min_y = min_view_h - 1;
  135. min_w = min_view_w;
  136. min_h = 1;
  137. self.bottomPgrogress.frame = CGRectMake(min_x, min_y, min_w, min_h);
  138. min_x = 0;
  139. min_y = iPhoneX ? 54 : 30;
  140. min_w = 170;
  141. min_h = 35;
  142. self.volumeBrightnessView.frame = CGRectMake(min_x, min_y, min_w, min_h);
  143. self.volumeBrightnessView.zf_centerX = self.zf_centerX;
  144. }
  145. - (void)dealloc {
  146. [[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];
  147. [self cancelAutoFadeOutControlView];
  148. }
  149. /// 添加所有子控件
  150. - (void)addAllSubViews {
  151. [self addSubview:self.portraitControlView];
  152. [self addSubview:self.landScapeControlView];
  153. [self addSubview:self.floatControlView];
  154. [self addSubview:self.activity];
  155. [self addSubview:self.failBtn];
  156. [self addSubview:self.fastView];
  157. [self.fastView addSubview:self.fastImageView];
  158. [self.fastView addSubview:self.fastTimeLabel];
  159. [self.fastView addSubview:self.fastProgressView];
  160. [self addSubview:self.bottomPgrogress];
  161. [self addSubview:self.volumeBrightnessView];
  162. }
  163. - (void)autoFadeOutControlView {
  164. self.controlViewAppeared = YES;
  165. [self cancelAutoFadeOutControlView];
  166. @weakify(self)
  167. self.afterBlock = dispatch_block_create(0, ^{
  168. @strongify(self)
  169. [self hideControlViewWithAnimated:YES];
  170. });
  171. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.autoHiddenTimeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(),self.afterBlock);
  172. }
  173. /// 取消延时隐藏controlView的方法
  174. - (void)cancelAutoFadeOutControlView {
  175. if (self.afterBlock) {
  176. dispatch_block_cancel(self.afterBlock);
  177. self.afterBlock = nil;
  178. }
  179. }
  180. /// 隐藏控制层
  181. - (void)hideControlViewWithAnimated:(BOOL)animated {
  182. self.controlViewAppeared = NO;
  183. if (self.controlViewAppearedCallback) {
  184. self.controlViewAppearedCallback(NO);
  185. }
  186. [UIView animateWithDuration:animated ? self.autoFadeTimeInterval : 0 animations:^{
  187. if (self.player.isFullScreen) {
  188. [self.landScapeControlView hideControlView];
  189. } else {
  190. if (!self.player.isSmallFloatViewShow) {
  191. [self.portraitControlView hideControlView];
  192. }
  193. }
  194. } completion:^(BOOL finished) {
  195. self.bottomPgrogress.hidden = NO;
  196. }];
  197. }
  198. /// 显示控制层
  199. - (void)showControlViewWithAnimated:(BOOL)animated {
  200. self.controlViewAppeared = YES;
  201. if (self.controlViewAppearedCallback) {
  202. self.controlViewAppearedCallback(YES);
  203. }
  204. [self autoFadeOutControlView];
  205. [UIView animateWithDuration:animated ? self.autoFadeTimeInterval : 0 animations:^{
  206. if (self.player.isFullScreen) {
  207. [self.landScapeControlView showControlView];
  208. } else {
  209. if (!self.player.isSmallFloatViewShow) {
  210. [self.portraitControlView showControlView];
  211. }
  212. }
  213. } completion:^(BOOL finished) {
  214. self.bottomPgrogress.hidden = YES;
  215. }];
  216. }
  217. /// 音量改变的通知
  218. - (void)volumeChanged:(NSNotification *)notification {
  219. NSDictionary *userInfo = notification.userInfo;
  220. NSString *reasonstr = userInfo[@"AVSystemController_AudioVolumeChangeReasonNotificationParameter"];
  221. if ([reasonstr isEqualToString:@"ExplicitVolumeChange"]) {
  222. float volume = [ userInfo[@"AVSystemController_AudioVolumeNotificationParameter"] floatValue];
  223. if (self.player.isFullScreen) {
  224. [self.volumeBrightnessView updateProgress:volume withVolumeBrightnessType:ZFVolumeBrightnessTypeVolume];
  225. } else {
  226. [self.volumeBrightnessView addSystemVolumeView];
  227. }
  228. }
  229. }
  230. #pragma mark - Public Method
  231. /// 重置控制层
  232. - (void)resetControlView {
  233. [self.portraitControlView resetControlView];
  234. [self.landScapeControlView resetControlView];
  235. [self cancelAutoFadeOutControlView];
  236. self.bottomPgrogress.value = 0;
  237. self.bottomPgrogress.bufferValue = 0;
  238. self.floatControlView.hidden = YES;
  239. self.failBtn.hidden = YES;
  240. self.volumeBrightnessView.hidden = YES;
  241. self.portraitControlView.hidden = self.player.isFullScreen;
  242. self.landScapeControlView.hidden = !self.player.isFullScreen;
  243. if (self.controlViewAppeared) {
  244. [self showControlViewWithAnimated:NO];
  245. } else {
  246. [self hideControlViewWithAnimated:NO];
  247. }
  248. }
  249. /// 设置标题、封面、全屏模式
  250. - (void)showTitle:(NSString *)title coverURLString:(NSString *)coverUrl fullScreenMode:(ZFFullScreenMode)fullScreenMode {
  251. UIImage *placeholder = [ZFUtilities imageWithColor:[UIColor colorWithRed:220/255.0 green:220/255.0 blue:220/255.0 alpha:1] size:self.bgImgView.bounds.size];
  252. [self showTitle:title coverURLString:coverUrl placeholderImage:placeholder fullScreenMode:fullScreenMode];
  253. }
  254. /// 设置标题、封面、默认占位图、全屏模式
  255. - (void)showTitle:(NSString *)title coverURLString:(NSString *)coverUrl placeholderImage:(UIImage *)placeholder fullScreenMode:(ZFFullScreenMode)fullScreenMode {
  256. [self resetControlView];
  257. [self layoutIfNeeded];
  258. [self setNeedsDisplay];
  259. [self.portraitControlView showTitle:title fullScreenMode:fullScreenMode];
  260. [self.landScapeControlView showTitle:title fullScreenMode:fullScreenMode];
  261. [self.coverImageView setImageWithURLString:coverUrl placeholder:placeholder];
  262. [self.bgImgView setImageWithURLString:coverUrl placeholder:placeholder];
  263. if (self.prepareShowControlView) {
  264. [self showControlViewWithAnimated:NO];
  265. } else {
  266. [self hideControlViewWithAnimated:NO];
  267. }
  268. }
  269. /// 设置标题、UIImage封面、全屏模式
  270. - (void)showTitle:(NSString *)title coverImage:(UIImage *)image fullScreenMode:(ZFFullScreenMode)fullScreenMode {
  271. [self resetControlView];
  272. [self layoutIfNeeded];
  273. [self setNeedsDisplay];
  274. [self.portraitControlView showTitle:title fullScreenMode:fullScreenMode];
  275. [self.landScapeControlView showTitle:title fullScreenMode:fullScreenMode];
  276. self.coverImageView.image = image;
  277. self.bgImgView.image = image;
  278. if (self.prepareShowControlView) {
  279. [self showControlViewWithAnimated:NO];
  280. } else {
  281. [self hideControlViewWithAnimated:NO];
  282. }
  283. }
  284. #pragma mark - ZFPlayerControlViewDelegate
  285. /// 手势筛选,返回NO不响应该手势
  286. - (BOOL)gestureTriggerCondition:(ZFPlayerGestureControl *)gestureControl gestureType:(ZFPlayerGestureType)gestureType gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer touch:(nonnull UITouch *)touch {
  287. CGPoint point = [touch locationInView:self];
  288. if (self.player.isSmallFloatViewShow && !self.player.isFullScreen && gestureType != ZFPlayerGestureTypeSingleTap) {
  289. return NO;
  290. }
  291. if (self.player.isFullScreen) {
  292. if (!self.customDisablePanMovingDirection) {
  293. /// 不禁用滑动方向
  294. self.player.disablePanMovingDirection = ZFPlayerDisablePanMovingDirectionNone;
  295. }
  296. return [self.landScapeControlView shouldResponseGestureWithPoint:point withGestureType:gestureType touch:touch];
  297. } else {
  298. if (!self.customDisablePanMovingDirection) {
  299. if (self.player.scrollView) { /// 列表时候禁止上下滑动(防止和列表滑动冲突)
  300. self.player.disablePanMovingDirection = ZFPlayerDisablePanMovingDirectionVertical;
  301. } else { /// 不禁用滑动方向
  302. self.player.disablePanMovingDirection = ZFPlayerDisablePanMovingDirectionNone;
  303. }
  304. }
  305. return [self.portraitControlView shouldResponseGestureWithPoint:point withGestureType:gestureType touch:touch];
  306. }
  307. }
  308. /// 单击手势事件
  309. - (void)gestureSingleTapped:(ZFPlayerGestureControl *)gestureControl {
  310. if (!self.player) return;
  311. if (self.player.isSmallFloatViewShow && !self.player.isFullScreen) {
  312. [self.player enterFullScreen:YES animated:YES];
  313. } else {
  314. if (self.controlViewAppeared) {
  315. [self hideControlViewWithAnimated:YES];
  316. } else {
  317. /// 显示之前先把控制层复位,先隐藏后显示
  318. [self hideControlViewWithAnimated:NO];
  319. [self showControlViewWithAnimated:YES];
  320. }
  321. }
  322. }
  323. /// 双击手势事件
  324. - (void)gestureDoubleTapped:(ZFPlayerGestureControl *)gestureControl {
  325. if (self.player.isFullScreen) {
  326. [self.landScapeControlView playOrPause];
  327. } else {
  328. [self.portraitControlView playOrPause];
  329. }
  330. }
  331. /// 开始滑动手势事件
  332. - (void)gestureBeganPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location {
  333. if (direction == ZFPanDirectionH) {
  334. self.sumTime = self.player.currentTime;
  335. }
  336. }
  337. /// 滑动中手势事件
  338. - (void)gestureChangedPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location withVelocity:(CGPoint)velocity {
  339. if (direction == ZFPanDirectionH) {
  340. // 每次滑动需要叠加时间
  341. self.sumTime += velocity.x / 200;
  342. // 需要限定sumTime的范围
  343. NSTimeInterval totalMovieDuration = self.player.totalTime;
  344. if (totalMovieDuration == 0) return;
  345. if (self.sumTime > totalMovieDuration) self.sumTime = totalMovieDuration;
  346. if (self.sumTime < 0) self.sumTime = 0;
  347. BOOL style = NO;
  348. if (velocity.x > 0) style = YES;
  349. if (velocity.x < 0) style = NO;
  350. if (velocity.x == 0) return;
  351. [self sliderValueChangingValue:self.sumTime/totalMovieDuration isForward:style];
  352. } else if (direction == ZFPanDirectionV) {
  353. if (location == ZFPanLocationLeft) { /// 调节亮度
  354. self.player.brightness -= (velocity.y) / 10000;
  355. [self.volumeBrightnessView updateProgress:self.player.brightness withVolumeBrightnessType:ZFVolumeBrightnessTypeumeBrightness];
  356. } else if (location == ZFPanLocationRight) { /// 调节声音
  357. self.player.volume -= (velocity.y) / 10000;
  358. if (self.player.isFullScreen) {
  359. [self.volumeBrightnessView updateProgress:self.player.volume withVolumeBrightnessType:ZFVolumeBrightnessTypeVolume];
  360. }
  361. }
  362. }
  363. }
  364. /// 滑动结束手势事件
  365. - (void)gestureEndedPan:(ZFPlayerGestureControl *)gestureControl panDirection:(ZFPanDirection)direction panLocation:(ZFPanLocation)location {
  366. @weakify(self)
  367. if (direction == ZFPanDirectionH && self.sumTime >= 0 && self.player.totalTime > 0) {
  368. [self.player seekToTime:self.sumTime completionHandler:^(BOOL 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. if (self.seekToPlay) {
  379. [self.player.currentPlayerManager play];
  380. }
  381. self.sumTime = 0;
  382. }
  383. }
  384. /// 捏合手势事件,这里改变了视频的填充模式
  385. - (void)gesturePinched:(ZFPlayerGestureControl *)gestureControl scale:(float)scale {
  386. if (scale > 1) {
  387. self.player.currentPlayerManager.scalingMode = ZFPlayerScalingModeAspectFill;
  388. } else {
  389. self.player.currentPlayerManager.scalingMode = ZFPlayerScalingModeAspectFit;
  390. }
  391. }
  392. /// 准备播放
  393. - (void)videoPlayer:(ZFPlayerController *)videoPlayer prepareToPlay:(NSURL *)assetURL {
  394. [self hideControlViewWithAnimated:NO];
  395. }
  396. /// 播放状态改变
  397. - (void)videoPlayer:(ZFPlayerController *)videoPlayer playStateChanged:(ZFPlayerPlaybackState)state {
  398. if (state == ZFPlayerPlayStatePlaying) {
  399. [self.portraitControlView playBtnSelectedState:YES];
  400. [self.landScapeControlView playBtnSelectedState:YES];
  401. self.failBtn.hidden = YES;
  402. /// 开始播放时候判断是否显示loading
  403. if (videoPlayer.currentPlayerManager.loadState == ZFPlayerLoadStateStalled && !self.prepareShowLoading) {
  404. [self.activity startAnimating];
  405. } else if ((videoPlayer.currentPlayerManager.loadState == ZFPlayerLoadStateStalled || videoPlayer.currentPlayerManager.loadState == ZFPlayerLoadStatePrepare) && self.prepareShowLoading) {
  406. [self.activity startAnimating];
  407. }
  408. } else if (state == ZFPlayerPlayStatePaused) {
  409. [self.portraitControlView playBtnSelectedState:NO];
  410. [self.landScapeControlView playBtnSelectedState:NO];
  411. /// 暂停的时候隐藏loading
  412. [self.activity stopAnimating];
  413. self.failBtn.hidden = YES;
  414. } else if (state == ZFPlayerPlayStatePlayFailed) {
  415. self.failBtn.hidden = NO;
  416. [self.activity stopAnimating];
  417. }
  418. }
  419. /// 加载状态改变
  420. - (void)videoPlayer:(ZFPlayerController *)videoPlayer loadStateChanged:(ZFPlayerLoadState)state {
  421. if (state == ZFPlayerLoadStatePrepare) {
  422. self.coverImageView.hidden = NO;
  423. [self.portraitControlView playBtnSelectedState:videoPlayer.currentPlayerManager.shouldAutoPlay];
  424. [self.landScapeControlView playBtnSelectedState:videoPlayer.currentPlayerManager.shouldAutoPlay];
  425. } else if (state == ZFPlayerLoadStatePlaythroughOK || state == ZFPlayerLoadStatePlayable) {
  426. self.coverImageView.hidden = YES;
  427. if (self.effectViewShow) {
  428. self.effectView.hidden = NO;
  429. } else {
  430. self.effectView.hidden = YES;
  431. self.player.currentPlayerManager.view.backgroundColor = [UIColor blackColor];
  432. }
  433. }
  434. if (state == ZFPlayerLoadStateStalled && videoPlayer.currentPlayerManager.isPlaying && !self.prepareShowLoading) {
  435. [self.activity startAnimating];
  436. } else if ((state == ZFPlayerLoadStateStalled || state == ZFPlayerLoadStatePrepare) && videoPlayer.currentPlayerManager.isPlaying && self.prepareShowLoading) {
  437. [self.activity startAnimating];
  438. } else {
  439. [self.activity stopAnimating];
  440. }
  441. }
  442. /// 播放进度改变回调
  443. - (void)videoPlayer:(ZFPlayerController *)videoPlayer currentTime:(NSTimeInterval)currentTime totalTime:(NSTimeInterval)totalTime {
  444. [self.portraitControlView videoPlayer:videoPlayer currentTime:currentTime totalTime:totalTime];
  445. [self.landScapeControlView videoPlayer:videoPlayer currentTime:currentTime totalTime:totalTime];
  446. if (!self.bottomPgrogress.isdragging) {
  447. self.bottomPgrogress.value = videoPlayer.progress;
  448. }
  449. }
  450. /// 缓冲改变回调
  451. - (void)videoPlayer:(ZFPlayerController *)videoPlayer bufferTime:(NSTimeInterval)bufferTime {
  452. [self.portraitControlView videoPlayer:videoPlayer bufferTime:bufferTime];
  453. [self.landScapeControlView videoPlayer:videoPlayer bufferTime:bufferTime];
  454. self.bottomPgrogress.bufferValue = videoPlayer.bufferProgress;
  455. }
  456. - (void)videoPlayer:(ZFPlayerController *)videoPlayer presentationSizeChanged:(CGSize)size {
  457. [self.landScapeControlView videoPlayer:videoPlayer presentationSizeChanged:size];
  458. }
  459. /// 视频view即将旋转
  460. - (void)videoPlayer:(ZFPlayerController *)videoPlayer orientationWillChange:(ZFOrientationObserver *)observer {
  461. self.portraitControlView.hidden = observer.isFullScreen;
  462. self.landScapeControlView.hidden = !observer.isFullScreen;
  463. if (videoPlayer.isSmallFloatViewShow) {
  464. self.floatControlView.hidden = observer.isFullScreen;
  465. self.portraitControlView.hidden = YES;
  466. if (observer.isFullScreen) {
  467. self.controlViewAppeared = NO;
  468. [self cancelAutoFadeOutControlView];
  469. }
  470. }
  471. if (self.controlViewAppeared) {
  472. [self showControlViewWithAnimated:NO];
  473. } else {
  474. [self hideControlViewWithAnimated:NO];
  475. }
  476. if (observer.isFullScreen) {
  477. [self.volumeBrightnessView removeSystemVolumeView];
  478. } else {
  479. [self.volumeBrightnessView addSystemVolumeView];
  480. }
  481. }
  482. /// 视频view已经旋转
  483. - (void)videoPlayer:(ZFPlayerController *)videoPlayer orientationDidChanged:(ZFOrientationObserver *)observer {
  484. if (self.controlViewAppeared) {
  485. [self showControlViewWithAnimated:NO];
  486. } else {
  487. [self hideControlViewWithAnimated:NO];
  488. }
  489. }
  490. /// 锁定旋转方向
  491. - (void)lockedVideoPlayer:(ZFPlayerController *)videoPlayer lockedScreen:(BOOL)locked {
  492. [self showControlViewWithAnimated:YES];
  493. }
  494. /// 列表滑动时视频view已经显示
  495. - (void)playerDidAppearInScrollView:(ZFPlayerController *)videoPlayer {
  496. if (!self.player.stopWhileNotVisible && !videoPlayer.isFullScreen) {
  497. self.floatControlView.hidden = YES;
  498. self.portraitControlView.hidden = NO;
  499. }
  500. }
  501. /// 列表滑动时视频view已经消失
  502. - (void)playerDidDisappearInScrollView:(ZFPlayerController *)videoPlayer {
  503. if (!self.player.stopWhileNotVisible && !videoPlayer.isFullScreen) {
  504. self.floatControlView.hidden = NO;
  505. self.portraitControlView.hidden = YES;
  506. }
  507. }
  508. - (void)videoPlayer:(ZFPlayerController *)videoPlayer floatViewShow:(BOOL)show {
  509. self.floatControlView.hidden = !show;
  510. self.portraitControlView.hidden = show;
  511. }
  512. #pragma mark - Private Method
  513. - (void)sliderValueChangingValue:(CGFloat)value isForward:(BOOL)forward {
  514. if (self.horizontalPanShowControlView) {
  515. /// 显示控制层
  516. [self showControlViewWithAnimated:NO];
  517. [self cancelAutoFadeOutControlView];
  518. }
  519. self.fastProgressView.value = value;
  520. self.fastView.hidden = NO;
  521. self.fastView.alpha = 1;
  522. if (forward) {
  523. self.fastImageView.image = ZFPlayer_Image(@"ZFPlayer_fast_forward");
  524. } else {
  525. self.fastImageView.image = ZFPlayer_Image(@"ZFPlayer_fast_backward");
  526. }
  527. NSString *draggedTime = [ZFUtilities convertTimeSecond:self.player.totalTime*value];
  528. NSString *totalTime = [ZFUtilities convertTimeSecond:self.player.totalTime];
  529. self.fastTimeLabel.text = [NSString stringWithFormat:@"%@ / %@",draggedTime,totalTime];
  530. /// 更新滑杆
  531. [self.portraitControlView sliderValueChanged:value currentTimeString:draggedTime];
  532. [self.landScapeControlView sliderValueChanged:value currentTimeString:draggedTime];
  533. self.bottomPgrogress.isdragging = YES;
  534. self.bottomPgrogress.value = value;
  535. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideFastView) object:nil];
  536. [self performSelector:@selector(hideFastView) withObject:nil afterDelay:0.1];
  537. if (self.fastViewAnimated) {
  538. [UIView animateWithDuration:0.4 animations:^{
  539. self.fastView.transform = CGAffineTransformMakeTranslation(forward?8:-8, 0);
  540. }];
  541. }
  542. }
  543. /// 隐藏快进视图
  544. - (void)hideFastView {
  545. [UIView animateWithDuration:0.4 animations:^{
  546. self.fastView.transform = CGAffineTransformIdentity;
  547. self.fastView.alpha = 0;
  548. } completion:^(BOOL finished) {
  549. self.fastView.hidden = YES;
  550. }];
  551. }
  552. /// 加载失败
  553. - (void)failBtnClick:(UIButton *)sender {
  554. [self.player.currentPlayerManager reloadPlayer];
  555. }
  556. #pragma mark - setter
  557. - (void)setPlayer:(ZFPlayerController *)player {
  558. _player = player;
  559. self.landScapeControlView.player = player;
  560. self.portraitControlView.player = player;
  561. /// 解决播放时候黑屏闪一下问题
  562. [player.currentPlayerManager.view insertSubview:self.bgImgView atIndex:0];
  563. [self.bgImgView addSubview:self.effectView];
  564. [player.currentPlayerManager.view insertSubview:self.coverImageView atIndex:1];
  565. self.coverImageView.frame = player.currentPlayerManager.view.bounds;
  566. self.coverImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  567. self.bgImgView.frame = player.currentPlayerManager.view.bounds;
  568. self.bgImgView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  569. self.effectView.frame = self.bgImgView.bounds;
  570. self.coverImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  571. }
  572. - (void)setSeekToPlay:(BOOL)seekToPlay {
  573. _seekToPlay = seekToPlay;
  574. self.portraitControlView.seekToPlay = seekToPlay;
  575. self.landScapeControlView.seekToPlay = seekToPlay;
  576. }
  577. - (void)setEffectViewShow:(BOOL)effectViewShow {
  578. _effectViewShow = effectViewShow;
  579. if (effectViewShow) {
  580. self.bgImgView.hidden = NO;
  581. } else {
  582. self.bgImgView.hidden = YES;
  583. }
  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. @weakify(self)
  609. _portraitControlView = [[ZFPortraitControlView alloc] init];
  610. _portraitControlView.sliderValueChanging = ^(CGFloat value, BOOL forward) {
  611. @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. @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. @weakify(self)
  634. _landScapeControlView = [[ZFLandScapeControlView alloc] init];
  635. _landScapeControlView.sliderValueChanging = ^(CGFloat value, BOOL forward) {
  636. @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. @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. - (UIImageView *)coverImageView {
  722. if (!_coverImageView) {
  723. _coverImageView = [[UIImageView alloc] init];
  724. _coverImageView.userInteractionEnabled = YES;
  725. _coverImageView.contentMode = UIViewContentModeScaleAspectFit;
  726. }
  727. return _coverImageView;
  728. }
  729. - (ZFSmallFloatControlView *)floatControlView {
  730. if (!_floatControlView) {
  731. _floatControlView = [[ZFSmallFloatControlView alloc] init];
  732. @weakify(self)
  733. _floatControlView.closeClickCallback = ^{
  734. @strongify(self)
  735. if (self.player.containerType == ZFPlayerContainerTypeCell) {
  736. [self.player stopCurrentPlayingCell];
  737. } else if (self.player.containerType == ZFPlayerContainerTypeView) {
  738. [self.player stopCurrentPlayingView];
  739. }
  740. [self resetControlView];
  741. };
  742. }
  743. return _floatControlView;
  744. }
  745. - (ZFVolumeBrightnessView *)volumeBrightnessView {
  746. if (!_volumeBrightnessView) {
  747. _volumeBrightnessView = [[ZFVolumeBrightnessView alloc] init];
  748. _volumeBrightnessView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
  749. _volumeBrightnessView.hidden = YES;
  750. }
  751. return _volumeBrightnessView;
  752. }
  753. - (void)setBackBtnClickCallback:(void (^)(void))backBtnClickCallback {
  754. _backBtnClickCallback = [backBtnClickCallback copy];
  755. self.landScapeControlView.backBtnClickCallback = _backBtnClickCallback;
  756. }
  757. @end