ZFPlayerController.m 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. //
  2. // ZFPlayerController.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 "ZFPlayerController.h"
  25. #import <objc/runtime.h>
  26. #import <MediaPlayer/MediaPlayer.h>
  27. #import <AVFoundation/AVFoundation.h>
  28. #import "UIScrollView+ZFPlayer.h"
  29. #import "ZFReachabilityManager.h"
  30. #import "ZFPlayer.h"
  31. @interface ZFPlayerController ()
  32. @property (nonatomic, strong) ZFPlayerNotification *notification;
  33. @property (nonatomic, weak) UIScrollView *scrollView;
  34. @property (nonatomic, strong) UISlider *volumeViewSlider;
  35. @property (nonatomic, assign) NSInteger containerViewTag;
  36. @property (nonatomic, assign) ZFPlayerContainerType containerType;
  37. /// The player's small container view.
  38. @property (nonatomic, strong) ZFFloatView *smallFloatView;
  39. /// Whether the small window is displayed.
  40. @property (nonatomic, assign) BOOL isSmallFloatViewShow;
  41. /// The indexPath is playing.
  42. @property (nonatomic, nullable) NSIndexPath *playingIndexPath;
  43. @end
  44. @implementation ZFPlayerController
  45. - (instancetype)init {
  46. self = [super init];
  47. if (self) {
  48. @weakify(self)
  49. [[ZFReachabilityManager sharedManager] startMonitoring];
  50. [[ZFReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(ZFReachabilityStatus status) {
  51. @strongify(self)
  52. if ([self.controlView respondsToSelector:@selector(videoPlayer:reachabilityChanged:)]) {
  53. [self.controlView videoPlayer:self reachabilityChanged:status];
  54. }
  55. }];
  56. [self configureVolume];
  57. }
  58. return self;
  59. }
  60. /// Get system volume
  61. - (void)configureVolume {
  62. MPVolumeView *volumeView = [[MPVolumeView alloc] init];
  63. self.volumeViewSlider = nil;
  64. for (UIView *view in [volumeView subviews]){
  65. if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
  66. self.volumeViewSlider = (UISlider *)view;
  67. break;
  68. }
  69. }
  70. }
  71. - (void)dealloc {
  72. [self.currentPlayerManager stop];
  73. }
  74. + (instancetype)playerWithPlayerManager:(id<ZFPlayerMediaPlayback>)playerManager containerView:(nonnull UIView *)containerView {
  75. ZFPlayerController *player = [[self alloc] initWithPlayerManager:playerManager containerView:containerView];
  76. return player;
  77. }
  78. + (instancetype)playerWithScrollView:(UIScrollView *)scrollView playerManager:(id<ZFPlayerMediaPlayback>)playerManager containerViewTag:(NSInteger)containerViewTag {
  79. ZFPlayerController *player = [[self alloc] initWithScrollView:scrollView playerManager:playerManager containerViewTag:containerViewTag];
  80. return player;
  81. }
  82. + (instancetype)playerWithScrollView:(UIScrollView *)scrollView playerManager:(id<ZFPlayerMediaPlayback>)playerManager containerView:(UIView *)containerView {
  83. ZFPlayerController *player = [[self alloc] initWithScrollView:scrollView playerManager:playerManager containerView:containerView];
  84. return player;
  85. }
  86. - (instancetype)initWithPlayerManager:(id<ZFPlayerMediaPlayback>)playerManager containerView:(nonnull UIView *)containerView {
  87. ZFPlayerController *player = [self init];
  88. player.containerView = containerView;
  89. player.currentPlayerManager = playerManager;
  90. player.containerType = ZFPlayerContainerTypeView;
  91. return player;
  92. }
  93. - (instancetype)initWithScrollView:(UIScrollView *)scrollView playerManager:(id<ZFPlayerMediaPlayback>)playerManager containerViewTag:(NSInteger)containerViewTag {
  94. ZFPlayerController *player = [self init];
  95. player.scrollView = scrollView;
  96. player.containerViewTag = containerViewTag;
  97. player.currentPlayerManager = playerManager;
  98. player.containerType = ZFPlayerContainerTypeCell;
  99. return player;
  100. }
  101. - (instancetype)initWithScrollView:(UIScrollView *)scrollView playerManager:(id<ZFPlayerMediaPlayback>)playerManager containerView:(UIView *)containerView {
  102. ZFPlayerController *player = [self init];
  103. player.scrollView = scrollView;
  104. player.containerView = containerView;
  105. player.currentPlayerManager = playerManager;
  106. player.containerType = ZFPlayerContainerTypeView;
  107. return player;
  108. }
  109. - (void)playerManagerCallbcak {
  110. @weakify(self)
  111. self.currentPlayerManager.playerPrepareToPlay = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, NSURL * _Nonnull assetURL) {
  112. @strongify(self)
  113. self.currentPlayerManager.view.hidden = NO;
  114. [self.notification addNotification];
  115. [self addDeviceOrientationObserver];
  116. if (self.scrollView) {
  117. self.scrollView.zf_stopPlay = NO;
  118. }
  119. [self layoutPlayerSubViews];
  120. if (self.playerPrepareToPlay) self.playerPrepareToPlay(asset,assetURL);
  121. if ([self.controlView respondsToSelector:@selector(videoPlayer:prepareToPlay:)]) {
  122. [self.controlView videoPlayer:self prepareToPlay:assetURL];
  123. }
  124. };
  125. self.currentPlayerManager.playerReadyToPlay = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, NSURL * _Nonnull assetURL) {
  126. @strongify(self)
  127. if (self.playerReadyToPlay) self.playerReadyToPlay(asset,assetURL);
  128. if (!self.customAudioSession) {
  129. // Apps using this category don't mute when the phone's mute button is turned on, but play sound when the phone is silent
  130. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
  131. [[AVAudioSession sharedInstance] setActive:YES error:nil];
  132. }
  133. if (self.viewControllerDisappear) self.pauseByEvent = YES;
  134. };
  135. self.currentPlayerManager.playerPlayTimeChanged = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, NSTimeInterval currentTime, NSTimeInterval duration) {
  136. @strongify(self)
  137. if (self.playerPlayTimeChanged) self.playerPlayTimeChanged(asset,currentTime,duration);
  138. if ([self.controlView respondsToSelector:@selector(videoPlayer:currentTime:totalTime:)]) {
  139. [self.controlView videoPlayer:self currentTime:currentTime totalTime:duration];
  140. }
  141. };
  142. self.currentPlayerManager.playerBufferTimeChanged = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, NSTimeInterval bufferTime) {
  143. @strongify(self)
  144. if ([self.controlView respondsToSelector:@selector(videoPlayer:bufferTime:)]) {
  145. [self.controlView videoPlayer:self bufferTime:bufferTime];
  146. }
  147. if (self.playerBufferTimeChanged) self.playerBufferTimeChanged(asset,bufferTime);
  148. };
  149. self.currentPlayerManager.playerPlayStateChanged = ^(id _Nonnull asset, ZFPlayerPlaybackState playState) {
  150. @strongify(self)
  151. if (self.playerPlayStateChanged) self.playerPlayStateChanged(asset, playState);
  152. if ([self.controlView respondsToSelector:@selector(videoPlayer:playStateChanged:)]) {
  153. [self.controlView videoPlayer:self playStateChanged:playState];
  154. }
  155. };
  156. self.currentPlayerManager.playerLoadStateChanged = ^(id _Nonnull asset, ZFPlayerLoadState loadState) {
  157. @strongify(self)
  158. if (self.playerLoadStateChanged) self.playerLoadStateChanged(asset, loadState);
  159. if ([self.controlView respondsToSelector:@selector(videoPlayer:loadStateChanged:)]) {
  160. [self.controlView videoPlayer:self loadStateChanged:loadState];
  161. }
  162. };
  163. self.currentPlayerManager.playerDidToEnd = ^(id _Nonnull asset) {
  164. @strongify(self)
  165. if (self.playerDidToEnd) self.playerDidToEnd(asset);
  166. if ([self.controlView respondsToSelector:@selector(videoPlayerPlayEnd:)]) {
  167. [self.controlView videoPlayerPlayEnd:self];
  168. }
  169. };
  170. self.currentPlayerManager.playerPlayFailed = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, id _Nonnull error) {
  171. @strongify(self)
  172. if (self.playerPlayFailed) self.playerPlayFailed(asset, error);
  173. if ([self.controlView respondsToSelector:@selector(videoPlayerPlayFailed:error:)]) {
  174. [self.controlView videoPlayerPlayFailed:self error:error];
  175. }
  176. };
  177. self.currentPlayerManager.presentationSizeChanged = ^(id<ZFPlayerMediaPlayback> _Nonnull asset, CGSize size){
  178. @strongify(self)
  179. if (self.orientationObserver.fullScreenMode == ZFFullScreenModeAutomatic) {
  180. if (size.width > size.height) {
  181. self.orientationObserver.fullScreenMode = ZFFullScreenModeLandscape;
  182. } else {
  183. self.orientationObserver.fullScreenMode = ZFFullScreenModePortrait;
  184. }
  185. }
  186. if (self.presentationSizeChanged) self.presentationSizeChanged(asset, size);
  187. if ([self.controlView respondsToSelector:@selector(videoPlayer:presentationSizeChanged:)]) {
  188. [self.controlView videoPlayer:self presentationSizeChanged:size];
  189. }
  190. };
  191. }
  192. - (void)layoutPlayerSubViews {
  193. if (self.containerView && self.currentPlayerManager.view) {
  194. UIView *superview = nil;
  195. if (self.isFullScreen) {
  196. superview = self.orientationObserver.fullScreenContainerView;
  197. } else if (self.containerView) {
  198. superview = self.containerView;
  199. }
  200. [superview addSubview:self.currentPlayerManager.view];
  201. [self.currentPlayerManager.view addSubview:self.controlView];
  202. self.currentPlayerManager.view.frame = superview.bounds;
  203. self.currentPlayerManager.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  204. self.controlView.frame = self.currentPlayerManager.view.bounds;
  205. self.controlView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  206. [self.orientationObserver updateRotateView:self.currentPlayerManager.view containerView:self.containerView];
  207. }
  208. }
  209. #pragma mark - getter
  210. - (ZFPlayerNotification *)notification {
  211. if (!_notification) {
  212. _notification = [[ZFPlayerNotification alloc] init];
  213. @weakify(self)
  214. _notification.willResignActive = ^(ZFPlayerNotification * _Nonnull registrar) {
  215. @strongify(self)
  216. if (self.isViewControllerDisappear) return;
  217. if (self.pauseWhenAppResignActive && self.currentPlayerManager.isPlaying) {
  218. self.pauseByEvent = YES;
  219. }
  220. self.orientationObserver.lockedScreen = YES;
  221. dispatch_async(dispatch_get_main_queue(), ^{
  222. [[UIApplication sharedApplication].keyWindow endEditing:YES];
  223. });
  224. if (!self.pauseWhenAppResignActive) {
  225. [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
  226. [[AVAudioSession sharedInstance] setActive:YES error:nil];
  227. }
  228. };
  229. _notification.didBecomeActive = ^(ZFPlayerNotification * _Nonnull registrar) {
  230. @strongify(self)
  231. if (self.isViewControllerDisappear) return;
  232. if (self.isPauseByEvent) self.pauseByEvent = NO;
  233. self.orientationObserver.lockedScreen = NO;
  234. };
  235. _notification.oldDeviceUnavailable = ^(ZFPlayerNotification * _Nonnull registrar) {
  236. @strongify(self)
  237. if (self.currentPlayerManager.isPlaying) {
  238. [self.currentPlayerManager play];
  239. }
  240. };
  241. }
  242. return _notification;
  243. }
  244. - (ZFFloatView *)smallFloatView {
  245. if (!_smallFloatView) {
  246. _smallFloatView = [[ZFFloatView alloc] init];
  247. _smallFloatView.parentView = [UIApplication sharedApplication].keyWindow;
  248. _smallFloatView.hidden = YES;
  249. }
  250. return _smallFloatView;
  251. }
  252. #pragma mark - setter
  253. - (void)setCurrentPlayerManager:(id<ZFPlayerMediaPlayback>)currentPlayerManager {
  254. if (!currentPlayerManager) return;
  255. if (_currentPlayerManager.isPreparedToPlay) {
  256. [_currentPlayerManager stop];
  257. [_currentPlayerManager.view removeFromSuperview];
  258. [self.orientationObserver removeDeviceOrientationObserver];
  259. [self.gestureControl removeGestureToView:self.currentPlayerManager.view];
  260. }
  261. _currentPlayerManager = currentPlayerManager;
  262. _currentPlayerManager.view.hidden = YES;
  263. self.gestureControl.disableTypes = self.disableGestureTypes;
  264. [self.gestureControl addGestureToView:currentPlayerManager.view];
  265. [self playerManagerCallbcak];
  266. [self.orientationObserver updateRotateView:currentPlayerManager.view containerView:self.containerView];
  267. self.controlView.player = self;
  268. [self layoutPlayerSubViews];
  269. }
  270. - (void)setContainerView:(UIView *)containerView {
  271. _containerView = containerView;
  272. if (self.scrollView) {
  273. self.scrollView.zf_containerView = containerView;
  274. }
  275. if (!containerView) return;
  276. containerView.userInteractionEnabled = YES;
  277. [self layoutPlayerSubViews];
  278. }
  279. - (void)setControlView:(UIView<ZFPlayerMediaControl> *)controlView {
  280. _controlView = controlView;
  281. if (!controlView) return;
  282. controlView.player = self;
  283. [self layoutPlayerSubViews];
  284. }
  285. - (void)setContainerType:(ZFPlayerContainerType)containerType {
  286. _containerType = containerType;
  287. if (self.scrollView) {
  288. self.scrollView.zf_containerType = containerType;
  289. }
  290. }
  291. @end
  292. @implementation ZFPlayerController (ZFPlayerTimeControl)
  293. - (NSTimeInterval)currentTime {
  294. return self.currentPlayerManager.currentTime;
  295. }
  296. - (NSTimeInterval)totalTime {
  297. return self.currentPlayerManager.totalTime;
  298. }
  299. - (NSTimeInterval)bufferTime {
  300. return self.currentPlayerManager.bufferTime;
  301. }
  302. - (float)progress {
  303. if (self.totalTime == 0) return 0;
  304. return self.currentTime/self.totalTime;
  305. }
  306. - (float)bufferProgress {
  307. if (self.totalTime == 0) return 0;
  308. return self.bufferTime/self.totalTime;
  309. }
  310. - (void)seekToTime:(NSTimeInterval)time completionHandler:(void (^)(BOOL))completionHandler {
  311. [self.currentPlayerManager seekToTime:time completionHandler:completionHandler];
  312. }
  313. @end
  314. @implementation ZFPlayerController (ZFPlayerPlaybackControl)
  315. - (void)playTheNext {
  316. if (self.assetURLs.count > 0) {
  317. NSInteger index = self.currentPlayIndex + 1;
  318. if (index >= self.assetURLs.count) return;
  319. NSURL *assetURL = [self.assetURLs objectAtIndex:index];
  320. self.assetURL = assetURL;
  321. self.currentPlayIndex = [self.assetURLs indexOfObject:assetURL];
  322. }
  323. }
  324. - (void)playThePrevious {
  325. if (self.assetURLs.count > 0) {
  326. NSInteger index = self.currentPlayIndex - 1;
  327. if (index < 0) return;
  328. NSURL *assetURL = [self.assetURLs objectAtIndex:index];
  329. self.assetURL = assetURL;
  330. self.currentPlayIndex = [self.assetURLs indexOfObject:assetURL];
  331. }
  332. }
  333. - (void)playTheIndex:(NSInteger)index {
  334. if (self.assetURLs.count > 0) {
  335. if (index >= self.assetURLs.count) return;
  336. NSURL *assetURL = [self.assetURLs objectAtIndex:index];
  337. self.assetURL = assetURL;
  338. self.currentPlayIndex = index;
  339. }
  340. }
  341. - (void)stop {
  342. [self.notification removeNotification];
  343. [self.orientationObserver removeDeviceOrientationObserver];
  344. if (self.isFullScreen && self.exitFullScreenWhenStop) {
  345. [self.orientationObserver exitFullScreenWithAnimated:NO];
  346. }
  347. [self.currentPlayerManager stop];
  348. [self.currentPlayerManager.view removeFromSuperview];
  349. if (self.scrollView) {
  350. self.scrollView.zf_stopPlay = YES;
  351. }
  352. }
  353. - (void)replaceCurrentPlayerManager:(id<ZFPlayerMediaPlayback>)playerManager {
  354. self.currentPlayerManager = playerManager;
  355. }
  356. //// Add video to the cell
  357. - (void)addPlayerViewToCell {
  358. self.isSmallFloatViewShow = NO;
  359. self.smallFloatView.hidden = YES;
  360. UIView *cell = [self.scrollView zf_getCellForIndexPath:self.playingIndexPath];
  361. self.containerView = [cell viewWithTag:self.containerViewTag];
  362. [self.containerView addSubview:self.currentPlayerManager.view];
  363. self.currentPlayerManager.view.frame = self.containerView.bounds;
  364. self.currentPlayerManager.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  365. [self.orientationObserver cellModelRotateView:self.currentPlayerManager.view rotateViewAtCell:cell playerViewTag:self.containerViewTag];
  366. if ([self.controlView respondsToSelector:@selector(videoPlayer:floatViewShow:)]) {
  367. [self.controlView videoPlayer:self floatViewShow:NO];
  368. }
  369. }
  370. //// Add video to the container view
  371. - (void)addPlayerViewToContainerView:(UIView *)containerView {
  372. self.isSmallFloatViewShow = NO;
  373. self.smallFloatView.hidden = YES;
  374. self.containerView = containerView;
  375. [self.containerView addSubview:self.currentPlayerManager.view];
  376. self.currentPlayerManager.view.frame = self.containerView.bounds;
  377. self.currentPlayerManager.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  378. [self.orientationObserver cellOtherModelRotateView:self.currentPlayerManager.view containerView:self.containerView];
  379. if ([self.controlView respondsToSelector:@selector(videoPlayer:floatViewShow:)]) {
  380. [self.controlView videoPlayer:self floatViewShow:NO];
  381. }
  382. }
  383. /// Add to the keyWindow
  384. - (void)addPlayerViewToKeyWindow {
  385. self.isSmallFloatViewShow = YES;
  386. self.smallFloatView.hidden = NO;
  387. [self.smallFloatView addSubview:self.currentPlayerManager.view];
  388. self.currentPlayerManager.view.frame = self.smallFloatView.bounds;
  389. self.currentPlayerManager.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  390. [self.orientationObserver cellOtherModelRotateView:self.currentPlayerManager.view containerView:self.smallFloatView];
  391. if ([self.controlView respondsToSelector:@selector(videoPlayer:floatViewShow:)]) {
  392. [self.controlView videoPlayer:self floatViewShow:YES];
  393. }
  394. }
  395. - (void)stopCurrentPlayingView {
  396. if (self.containerView) {
  397. [self stop];
  398. self.isSmallFloatViewShow = NO;
  399. if (self.smallFloatView) self.smallFloatView.hidden = YES;
  400. }
  401. }
  402. - (void)stopCurrentPlayingCell {
  403. if (self.scrollView.zf_playingIndexPath) {
  404. [self stop];
  405. self.isSmallFloatViewShow = NO;
  406. self.playingIndexPath = nil;
  407. if (self.smallFloatView) self.smallFloatView.hidden = YES;
  408. }
  409. }
  410. #pragma mark - getter
  411. - (NSURL *)assetURL {
  412. return objc_getAssociatedObject(self, _cmd);
  413. }
  414. - (NSArray<NSURL *> *)assetURLs {
  415. return objc_getAssociatedObject(self, _cmd);
  416. }
  417. - (BOOL)isLastAssetURL {
  418. if (self.assetURLs.count > 0) {
  419. return self.assetURL == self.assetURLs.lastObject;
  420. }
  421. return NO;
  422. }
  423. - (BOOL)isFirstAssetURL {
  424. if (self.assetURLs.count > 0) {
  425. return self.assetURL == self.assetURLs.firstObject;
  426. }
  427. return NO;
  428. }
  429. - (BOOL)isPauseByEvent {
  430. return [objc_getAssociatedObject(self, _cmd) boolValue];
  431. }
  432. - (float)brightness {
  433. return [UIScreen mainScreen].brightness;
  434. }
  435. - (float)volume {
  436. CGFloat volume = self.volumeViewSlider.value;
  437. if (volume == 0) {
  438. volume = [[AVAudioSession sharedInstance] outputVolume];
  439. }
  440. return volume;
  441. }
  442. - (BOOL)isMuted {
  443. return self.volume == 0;
  444. }
  445. - (float)lastVolumeValue {
  446. return [objc_getAssociatedObject(self, _cmd) floatValue];
  447. }
  448. - (ZFPlayerPlaybackState)playState {
  449. return self.currentPlayerManager.playState;
  450. }
  451. - (BOOL)isPlaying {
  452. return self.currentPlayerManager.isPlaying;
  453. }
  454. - (BOOL)pauseWhenAppResignActive {
  455. NSNumber *number = objc_getAssociatedObject(self, _cmd);
  456. if (number) return number.boolValue;
  457. self.pauseWhenAppResignActive = YES;
  458. return YES;
  459. }
  460. - (void (^)(id<ZFPlayerMediaPlayback> _Nonnull, NSURL * _Nonnull))playerPrepareToPlay {
  461. return objc_getAssociatedObject(self, _cmd);
  462. }
  463. - (void (^)(id<ZFPlayerMediaPlayback> _Nonnull, NSURL * _Nonnull))playerReadyToPlay {
  464. return objc_getAssociatedObject(self, _cmd);
  465. }
  466. - (void (^)(id<ZFPlayerMediaPlayback> _Nonnull, NSTimeInterval, NSTimeInterval))playerPlayTimeChanged {
  467. return objc_getAssociatedObject(self, _cmd);
  468. }
  469. - (void (^)(id<ZFPlayerMediaPlayback> _Nonnull, NSTimeInterval))playerBufferTimeChanged {
  470. return objc_getAssociatedObject(self, _cmd);
  471. }
  472. - (void (^)(id<ZFPlayerMediaPlayback> _Nonnull, ZFPlayerPlaybackState))playerPlayStateChanged {
  473. return objc_getAssociatedObject(self, _cmd);
  474. }
  475. - (void (^)(id<ZFPlayerMediaPlayback> _Nonnull, ZFPlayerLoadState))playerLoadStateChanged {
  476. return objc_getAssociatedObject(self, _cmd);
  477. }
  478. - (void (^)(id<ZFPlayerMediaPlayback> _Nonnull))playerDidToEnd {
  479. return objc_getAssociatedObject(self, _cmd);
  480. }
  481. - (void (^)(id<ZFPlayerMediaPlayback> _Nonnull, id _Nonnull))playerPlayFailed {
  482. return objc_getAssociatedObject(self, _cmd);
  483. }
  484. - (void (^)(id<ZFPlayerMediaPlayback> _Nonnull, CGSize ))presentationSizeChanged {
  485. return objc_getAssociatedObject(self, _cmd);
  486. }
  487. - (NSInteger)currentPlayIndex {
  488. return [objc_getAssociatedObject(self, _cmd) integerValue];
  489. }
  490. - (BOOL)isViewControllerDisappear {
  491. return [objc_getAssociatedObject(self, _cmd) boolValue];
  492. }
  493. - (BOOL)customAudioSession {
  494. return [objc_getAssociatedObject(self, _cmd) boolValue];
  495. }
  496. #pragma mark - setter
  497. - (void)setAssetURL:(NSURL *)assetURL {
  498. objc_setAssociatedObject(self, @selector(assetURL), assetURL, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  499. self.currentPlayerManager.assetURL = assetURL;
  500. }
  501. - (void)setAssetURLs:(NSArray<NSURL *> * _Nullable)assetURLs {
  502. objc_setAssociatedObject(self, @selector(assetURLs), assetURLs, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  503. }
  504. - (void)setVolume:(float)volume {
  505. volume = MIN(MAX(0, volume), 1);
  506. objc_setAssociatedObject(self, @selector(volume), @(volume), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  507. self.volumeViewSlider.value = volume;
  508. }
  509. - (void)setMuted:(BOOL)muted {
  510. if (muted) {
  511. if (self.volumeViewSlider.value > 0) {
  512. self.lastVolumeValue = self.volumeViewSlider.value;
  513. }
  514. self.volumeViewSlider.value = 0;
  515. } else {
  516. self.volumeViewSlider.value = self.lastVolumeValue;
  517. }
  518. }
  519. - (void)setLastVolumeValue:(float)lastVolumeValue {
  520. objc_setAssociatedObject(self, @selector(lastVolumeValue), @(lastVolumeValue), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  521. }
  522. - (void)setBrightness:(float)brightness {
  523. brightness = MIN(MAX(0, brightness), 1);
  524. objc_setAssociatedObject(self, @selector(brightness), @(brightness), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  525. [UIScreen mainScreen].brightness = brightness;
  526. }
  527. - (void)setPauseByEvent:(BOOL)pauseByEvent {
  528. objc_setAssociatedObject(self, @selector(isPauseByEvent), @(pauseByEvent), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  529. if (pauseByEvent) {
  530. [self.currentPlayerManager pause];
  531. } else {
  532. [self.currentPlayerManager play];
  533. }
  534. }
  535. - (void)setPauseWhenAppResignActive:(BOOL)pauseWhenAppResignActive {
  536. objc_setAssociatedObject(self, @selector(pauseWhenAppResignActive), @(pauseWhenAppResignActive), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  537. }
  538. - (void)setPlayerPrepareToPlay:(void (^)(id<ZFPlayerMediaPlayback> _Nonnull, NSURL * _Nonnull))playerPrepareToPlay {
  539. objc_setAssociatedObject(self, @selector(playerPrepareToPlay), playerPrepareToPlay, OBJC_ASSOCIATION_COPY);
  540. }
  541. - (void)setPlayerReadyToPlay:(void (^)(id<ZFPlayerMediaPlayback> _Nonnull, NSURL * _Nonnull))playerReadyToPlay {
  542. objc_setAssociatedObject(self, @selector(playerReadyToPlay), playerReadyToPlay, OBJC_ASSOCIATION_COPY);
  543. }
  544. - (void)setPlayerPlayTimeChanged:(void (^)(id<ZFPlayerMediaPlayback> _Nonnull, NSTimeInterval, NSTimeInterval))playerPlayTimeChanged {
  545. objc_setAssociatedObject(self, @selector(playerPlayTimeChanged), playerPlayTimeChanged, OBJC_ASSOCIATION_COPY);
  546. }
  547. - (void)setPlayerBufferTimeChanged:(void (^)(id<ZFPlayerMediaPlayback> _Nonnull, NSTimeInterval))playerBufferTimeChanged {
  548. objc_setAssociatedObject(self, @selector(playerBufferTimeChanged), playerBufferTimeChanged, OBJC_ASSOCIATION_COPY);
  549. }
  550. - (void)setPlayerPlayStateChanged:(void (^)(id<ZFPlayerMediaPlayback> _Nonnull, ZFPlayerPlaybackState))playerPlayStateChanged {
  551. objc_setAssociatedObject(self, @selector(playerPlayStateChanged), playerPlayStateChanged, OBJC_ASSOCIATION_COPY);
  552. }
  553. - (void)setPlayerLoadStateChanged:(void (^)(id<ZFPlayerMediaPlayback> _Nonnull, ZFPlayerLoadState))playerLoadStateChanged {
  554. objc_setAssociatedObject(self, @selector(playerLoadStateChanged), playerLoadStateChanged, OBJC_ASSOCIATION_COPY);
  555. }
  556. - (void)setPlayerDidToEnd:(void (^)(id<ZFPlayerMediaPlayback> _Nonnull))playerDidToEnd {
  557. objc_setAssociatedObject(self, @selector(playerDidToEnd), playerDidToEnd, OBJC_ASSOCIATION_COPY);
  558. }
  559. - (void)setPlayerPlayFailed:(void (^)(id<ZFPlayerMediaPlayback> _Nonnull, id _Nonnull))playerPlayFailed {
  560. objc_setAssociatedObject(self, @selector(playerPlayFailed), playerPlayFailed, OBJC_ASSOCIATION_COPY);
  561. }
  562. - (void)setPresentationSizeChanged:(void (^)(id<ZFPlayerMediaPlayback> _Nonnull, CGSize))presentationSizeChanged {
  563. objc_setAssociatedObject(self, @selector(presentationSizeChanged), presentationSizeChanged, OBJC_ASSOCIATION_COPY);
  564. }
  565. - (void)setCurrentPlayIndex:(NSInteger)currentPlayIndex {
  566. objc_setAssociatedObject(self, @selector(currentPlayIndex), @(currentPlayIndex), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  567. }
  568. - (void)setViewControllerDisappear:(BOOL)viewControllerDisappear {
  569. objc_setAssociatedObject(self, @selector(isViewControllerDisappear), @(viewControllerDisappear), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  570. if (self.scrollView) self.scrollView.zf_viewControllerDisappear = viewControllerDisappear;
  571. if (!self.currentPlayerManager.isPreparedToPlay) return;
  572. if (viewControllerDisappear) {
  573. [self removeDeviceOrientationObserver];
  574. if (self.currentPlayerManager.isPlaying) self.pauseByEvent = YES;
  575. } else {
  576. if (self.isPauseByEvent) self.pauseByEvent = NO;
  577. [self addDeviceOrientationObserver];
  578. }
  579. }
  580. - (void)setCustomAudioSession:(BOOL)customAudioSession {
  581. objc_setAssociatedObject(self, @selector(customAudioSession), @(customAudioSession), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  582. }
  583. @end
  584. @implementation ZFPlayerController (ZFPlayerOrientationRotation)
  585. - (void)addDeviceOrientationObserver {
  586. [self.orientationObserver addDeviceOrientationObserver];
  587. }
  588. - (void)removeDeviceOrientationObserver {
  589. [self.orientationObserver removeDeviceOrientationObserver];
  590. }
  591. - (void)enterLandscapeFullScreen:(UIInterfaceOrientation)orientation animated:(BOOL)animated {
  592. self.orientationObserver.fullScreenMode = ZFFullScreenModeLandscape;
  593. [self.orientationObserver enterLandscapeFullScreen:orientation animated:animated];
  594. }
  595. - (void)enterPortraitFullScreen:(BOOL)fullScreen animated:(BOOL)animated {
  596. self.orientationObserver.fullScreenMode = ZFFullScreenModePortrait;
  597. [self.orientationObserver enterPortraitFullScreen:fullScreen animated:animated];
  598. }
  599. - (void)enterFullScreen:(BOOL)fullScreen animated:(BOOL)animated {
  600. if (self.orientationObserver.fullScreenMode == ZFFullScreenModePortrait) {
  601. [self.orientationObserver enterPortraitFullScreen:fullScreen animated:animated];
  602. } else {
  603. UIInterfaceOrientation orientation = UIInterfaceOrientationUnknown;
  604. orientation = fullScreen? UIInterfaceOrientationLandscapeRight : UIInterfaceOrientationPortrait;
  605. [self.orientationObserver enterLandscapeFullScreen:orientation animated:animated];
  606. }
  607. }
  608. - (BOOL)shouldForceDeviceOrientation {
  609. return self.forceDeviceOrientation;
  610. }
  611. #pragma mark - getter
  612. - (ZFOrientationObserver *)orientationObserver {
  613. @weakify(self)
  614. ZFOrientationObserver *orientationObserver = objc_getAssociatedObject(self, _cmd);
  615. if (!orientationObserver) {
  616. orientationObserver = [[ZFOrientationObserver alloc] init];
  617. orientationObserver.orientationWillChange = ^(ZFOrientationObserver * _Nonnull observer, BOOL isFullScreen) {
  618. @strongify(self)
  619. if (self.orientationWillChange) self.orientationWillChange(self, isFullScreen);
  620. if ([self.controlView respondsToSelector:@selector(videoPlayer:orientationWillChange:)]) {
  621. [self.controlView videoPlayer:self orientationWillChange:observer];
  622. }
  623. [self.controlView setNeedsLayout];
  624. [self.controlView layoutIfNeeded];
  625. };
  626. orientationObserver.orientationDidChanged = ^(ZFOrientationObserver * _Nonnull observer, BOOL isFullScreen) {
  627. @strongify(self)
  628. if (self.orientationDidChanged) self.orientationDidChanged(self, isFullScreen);
  629. if ([self.controlView respondsToSelector:@selector(videoPlayer:orientationDidChanged:)]) {
  630. [self.controlView videoPlayer:self orientationDidChanged:observer];
  631. }
  632. };
  633. objc_setAssociatedObject(self, _cmd, orientationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  634. }
  635. return orientationObserver;
  636. }
  637. - (void (^)(ZFPlayerController * _Nonnull, BOOL))orientationWillChange {
  638. return objc_getAssociatedObject(self, _cmd);
  639. }
  640. - (void (^)(ZFPlayerController * _Nonnull, BOOL))orientationDidChanged {
  641. return objc_getAssociatedObject(self, _cmd);
  642. }
  643. - (BOOL)isFullScreen {
  644. return self.orientationObserver.isFullScreen;
  645. }
  646. - (BOOL)exitFullScreenWhenStop {
  647. NSNumber *number = objc_getAssociatedObject(self, _cmd);
  648. if (number) return number.boolValue;
  649. self.exitFullScreenWhenStop = YES;
  650. return YES;
  651. }
  652. - (UIInterfaceOrientation)currentOrientation {
  653. return self.orientationObserver.currentOrientation;
  654. }
  655. - (BOOL)isStatusBarHidden {
  656. return [objc_getAssociatedObject(self, _cmd) boolValue];
  657. }
  658. - (BOOL)isLockedScreen {
  659. return [objc_getAssociatedObject(self, _cmd) boolValue];
  660. }
  661. - (BOOL)shouldAutorotate {
  662. return [self shouldForceDeviceOrientation];
  663. }
  664. - (BOOL)allowOrentitaionRotation {
  665. NSNumber *number = objc_getAssociatedObject(self, _cmd);
  666. if (number) return number.boolValue;
  667. self.allowOrentitaionRotation = YES;
  668. return YES;
  669. }
  670. - (BOOL)forceDeviceOrientation {
  671. return [objc_getAssociatedObject(self, _cmd) boolValue];
  672. }
  673. #pragma mark - setter
  674. - (void)setOrientationWillChange:(void (^)(ZFPlayerController * _Nonnull, BOOL))orientationWillChange {
  675. objc_setAssociatedObject(self, @selector(orientationWillChange), orientationWillChange, OBJC_ASSOCIATION_COPY_NONATOMIC);
  676. }
  677. - (void)setOrientationDidChanged:(void (^)(ZFPlayerController * _Nonnull, BOOL))orientationDidChanged {
  678. objc_setAssociatedObject(self, @selector(orientationDidChanged), orientationDidChanged, OBJC_ASSOCIATION_COPY_NONATOMIC);
  679. }
  680. - (void)setStatusBarHidden:(BOOL)statusBarHidden {
  681. objc_setAssociatedObject(self, @selector(isStatusBarHidden), @(statusBarHidden), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  682. self.orientationObserver.statusBarHidden = statusBarHidden;
  683. }
  684. - (void)setLockedScreen:(BOOL)lockedScreen {
  685. objc_setAssociatedObject(self, @selector(isLockedScreen), @(lockedScreen), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  686. self.orientationObserver.lockedScreen = lockedScreen;
  687. if ([self.controlView respondsToSelector:@selector(lockedVideoPlayer:lockedScreen:)]) {
  688. [self.controlView lockedVideoPlayer:self lockedScreen:lockedScreen];
  689. }
  690. }
  691. - (void)setAllowOrentitaionRotation:(BOOL)allowOrentitaionRotation {
  692. objc_setAssociatedObject(self, @selector(allowOrentitaionRotation), @(allowOrentitaionRotation), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  693. self.orientationObserver.allowOrentitaionRotation = allowOrentitaionRotation;
  694. }
  695. - (void)setForceDeviceOrientation:(BOOL)forceDeviceOrientation {
  696. objc_setAssociatedObject(self, @selector(forceDeviceOrientation), @(forceDeviceOrientation), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  697. self.orientationObserver.forceDeviceOrientation = forceDeviceOrientation;
  698. }
  699. - (void)setExitFullScreenWhenStop:(BOOL)exitFullScreenWhenStop {
  700. objc_setAssociatedObject(self, @selector(exitFullScreenWhenStop), @(exitFullScreenWhenStop), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  701. }
  702. @end
  703. @implementation ZFPlayerController (ZFPlayerViewGesture)
  704. #pragma mark - getter
  705. - (ZFPlayerGestureControl *)gestureControl {
  706. ZFPlayerGestureControl *gestureControl = objc_getAssociatedObject(self, _cmd);
  707. if (!gestureControl) {
  708. gestureControl = [[ZFPlayerGestureControl alloc] init];
  709. @weakify(self)
  710. gestureControl.triggerCondition = ^BOOL(ZFPlayerGestureControl * _Nonnull control, ZFPlayerGestureType type, UIGestureRecognizer * _Nonnull gesture, UITouch *touch) {
  711. @strongify(self)
  712. if ([self.controlView respondsToSelector:@selector(gestureTriggerCondition:gestureType:gestureRecognizer:touch:)]) {
  713. return [self.controlView gestureTriggerCondition:control gestureType:type gestureRecognizer:gesture touch:touch];
  714. }
  715. return YES;
  716. };
  717. gestureControl.singleTapped = ^(ZFPlayerGestureControl * _Nonnull control) {
  718. @strongify(self)
  719. if ([self.controlView respondsToSelector:@selector(gestureSingleTapped:)]) {
  720. [self.controlView gestureSingleTapped:control];
  721. }
  722. };
  723. gestureControl.doubleTapped = ^(ZFPlayerGestureControl * _Nonnull control) {
  724. @strongify(self)
  725. if ([self.controlView respondsToSelector:@selector(gestureDoubleTapped:)]) {
  726. [self.controlView gestureDoubleTapped:control];
  727. }
  728. };
  729. gestureControl.beganPan = ^(ZFPlayerGestureControl * _Nonnull control, ZFPanDirection direction, ZFPanLocation location) {
  730. @strongify(self)
  731. if ([self.controlView respondsToSelector:@selector(gestureBeganPan:panDirection:panLocation:)]) {
  732. [self.controlView gestureBeganPan:control panDirection:direction panLocation:location];
  733. }
  734. };
  735. gestureControl.changedPan = ^(ZFPlayerGestureControl * _Nonnull control, ZFPanDirection direction, ZFPanLocation location, CGPoint velocity) {
  736. @strongify(self)
  737. if ([self.controlView respondsToSelector:@selector(gestureChangedPan:panDirection:panLocation:withVelocity:)]) {
  738. [self.controlView gestureChangedPan:control panDirection:direction panLocation:location withVelocity:velocity];
  739. }
  740. };
  741. gestureControl.endedPan = ^(ZFPlayerGestureControl * _Nonnull control, ZFPanDirection direction, ZFPanLocation location) {
  742. @strongify(self)
  743. if ([self.controlView respondsToSelector:@selector(gestureEndedPan:panDirection:panLocation:)]) {
  744. [self.controlView gestureEndedPan:control panDirection:direction panLocation:location];
  745. }
  746. };
  747. gestureControl.pinched = ^(ZFPlayerGestureControl * _Nonnull control, float scale) {
  748. @strongify(self)
  749. if ([self.controlView respondsToSelector:@selector(gesturePinched:scale:)]) {
  750. [self.controlView gesturePinched:control scale:scale];
  751. }
  752. };
  753. objc_setAssociatedObject(self, _cmd, gestureControl, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  754. }
  755. return gestureControl;
  756. }
  757. - (ZFPlayerDisableGestureTypes)disableGestureTypes {
  758. return [objc_getAssociatedObject(self, _cmd) integerValue];
  759. }
  760. - (ZFPlayerDisablePanMovingDirection)disablePanMovingDirection {
  761. return [objc_getAssociatedObject(self, _cmd) integerValue];
  762. }
  763. #pragma mark - setter
  764. - (void)setDisableGestureTypes:(ZFPlayerDisableGestureTypes)disableGestureTypes {
  765. objc_setAssociatedObject(self, @selector(disableGestureTypes), @(disableGestureTypes), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  766. self.gestureControl.disableTypes = disableGestureTypes;
  767. }
  768. - (void)setDisablePanMovingDirection:(ZFPlayerDisablePanMovingDirection)disablePanMovingDirection {
  769. objc_setAssociatedObject(self, @selector(disablePanMovingDirection), @(disablePanMovingDirection), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  770. self.gestureControl.disablePanMovingDirection = disablePanMovingDirection;
  771. }
  772. @end
  773. @implementation ZFPlayerController (ZFPlayerScrollView)
  774. + (void)load {
  775. static dispatch_once_t onceToken;
  776. dispatch_once(&onceToken, ^{
  777. SEL selectors[] = {
  778. NSSelectorFromString(@"dealloc")
  779. };
  780. for (NSInteger index = 0; index < sizeof(selectors) / sizeof(SEL); ++index) {
  781. SEL originalSelector = selectors[index];
  782. SEL swizzledSelector = NSSelectorFromString([@"zf_" stringByAppendingString:NSStringFromSelector(originalSelector)]);
  783. Method originalMethod = class_getInstanceMethod(self, originalSelector);
  784. Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
  785. if (class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))) {
  786. class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
  787. } else {
  788. method_exchangeImplementations(originalMethod, swizzledMethod);
  789. }
  790. }
  791. });
  792. }
  793. - (void)zf_dealloc {
  794. [self.smallFloatView removeFromSuperview];
  795. self.smallFloatView = nil;
  796. [self zf_dealloc];
  797. }
  798. #pragma mark - setter
  799. - (void)setScrollView:(UIScrollView *)scrollView {
  800. objc_setAssociatedObject(self, @selector(scrollView), scrollView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  801. self.scrollView.zf_WWANAutoPlay = self.isWWANAutoPlay;
  802. @weakify(self)
  803. scrollView.zf_playerWillAppearInScrollView = ^(NSIndexPath * _Nonnull indexPath) {
  804. @strongify(self)
  805. if (self.isFullScreen) return;
  806. if (self.zf_playerWillAppearInScrollView) self.zf_playerWillAppearInScrollView(indexPath);
  807. if ([self.controlView respondsToSelector:@selector(playerDidAppearInScrollView:)]) {
  808. [self.controlView playerDidAppearInScrollView:self];
  809. }
  810. };
  811. scrollView.zf_playerDidAppearInScrollView = ^(NSIndexPath * _Nonnull indexPath) {
  812. @strongify(self)
  813. if (self.isFullScreen) return;
  814. if (self.zf_playerDidAppearInScrollView) self.zf_playerDidAppearInScrollView(indexPath);
  815. if ([self.controlView respondsToSelector:@selector(playerDidAppearInScrollView:)]) {
  816. [self.controlView playerDidAppearInScrollView:self];
  817. }
  818. };
  819. scrollView.zf_playerWillDisappearInScrollView = ^(NSIndexPath * _Nonnull indexPath) {
  820. @strongify(self)
  821. if (self.isFullScreen) return;
  822. if (self.zf_playerWillDisappearInScrollView) self.zf_playerWillDisappearInScrollView(indexPath);
  823. if ([self.controlView respondsToSelector:@selector(playerWillDisappearInScrollView:)]) {
  824. [self.controlView playerWillDisappearInScrollView:self];
  825. }
  826. };
  827. scrollView.zf_playerDidDisappearInScrollView = ^(NSIndexPath * _Nonnull indexPath) {
  828. @strongify(self)
  829. if (self.isFullScreen) return;
  830. if (self.zf_playerDidDisappearInScrollView) self.zf_playerDidDisappearInScrollView(indexPath);
  831. if ([self.controlView respondsToSelector:@selector(playerDidDisappearInScrollView:)]) {
  832. [self.controlView playerDidDisappearInScrollView:self];
  833. }
  834. };
  835. scrollView.zf_playerAppearingInScrollView = ^(NSIndexPath * _Nonnull indexPath, CGFloat playerApperaPercent) {
  836. @strongify(self)
  837. if (self.isFullScreen) return;
  838. if (self.zf_playerAppearingInScrollView) self.zf_playerAppearingInScrollView(indexPath, playerApperaPercent);
  839. if ([self.controlView respondsToSelector:@selector(playerAppearingInScrollView:playerApperaPercent:)]) {
  840. [self.controlView playerAppearingInScrollView:self playerApperaPercent:playerApperaPercent];
  841. }
  842. if (!self.stopWhileNotVisible && playerApperaPercent >= self.playerApperaPercent) {
  843. if (self.containerType == ZFPlayerContainerTypeView) {
  844. [self addPlayerViewToContainerView:self.containerView];
  845. } else if (self.containerType == ZFPlayerContainerTypeCell) {
  846. [self addPlayerViewToCell];
  847. }
  848. }
  849. };
  850. scrollView.zf_playerDisappearingInScrollView = ^(NSIndexPath * _Nonnull indexPath, CGFloat playerDisapperaPercent) {
  851. @strongify(self)
  852. if (self.isFullScreen) return;
  853. if (self.zf_playerDisappearingInScrollView) self.zf_playerDisappearingInScrollView(indexPath, playerDisapperaPercent);
  854. if ([self.controlView respondsToSelector:@selector(playerDisappearingInScrollView:playerDisapperaPercent:)]) {
  855. [self.controlView playerDisappearingInScrollView:self playerDisapperaPercent:playerDisapperaPercent];
  856. }
  857. /// stop playing
  858. if (self.stopWhileNotVisible && playerDisapperaPercent >= self.playerDisapperaPercent) {
  859. if (self.containerType == ZFPlayerContainerTypeView) {
  860. [self stopCurrentPlayingView];
  861. } else if (self.containerType == ZFPlayerContainerTypeCell) {
  862. [self stopCurrentPlayingCell];
  863. }
  864. }
  865. /// add to window
  866. if (!self.stopWhileNotVisible && playerDisapperaPercent >= self.playerDisapperaPercent) [self addPlayerViewToKeyWindow];
  867. };
  868. scrollView.zf_playerShouldPlayInScrollView = ^(NSIndexPath * _Nonnull indexPath) {
  869. @strongify(self)
  870. if (self.zf_playerShouldPlayInScrollView) self.zf_playerShouldPlayInScrollView(indexPath);
  871. };
  872. scrollView.zf_scrollViewDidEndScrollingCallback = ^(NSIndexPath * _Nonnull indexPath) {
  873. @strongify(self)
  874. if (self.zf_scrollViewDidEndScrollingCallback) self.zf_scrollViewDidEndScrollingCallback(indexPath);
  875. };
  876. }
  877. - (void)setWWANAutoPlay:(BOOL)WWANAutoPlay {
  878. objc_setAssociatedObject(self, @selector(isWWANAutoPlay), @(WWANAutoPlay), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  879. if (self.scrollView) self.scrollView.zf_WWANAutoPlay = self.isWWANAutoPlay;
  880. }
  881. - (void)setStopWhileNotVisible:(BOOL)stopWhileNotVisible {
  882. self.scrollView.zf_stopWhileNotVisible = stopWhileNotVisible;
  883. objc_setAssociatedObject(self, @selector(stopWhileNotVisible), @(stopWhileNotVisible), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  884. }
  885. - (void)setContainerViewTag:(NSInteger)containerViewTag {
  886. objc_setAssociatedObject(self, @selector(containerViewTag), @(containerViewTag), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  887. self.scrollView.zf_containerViewTag = containerViewTag;
  888. }
  889. - (void)setPlayingIndexPath:(NSIndexPath *)playingIndexPath {
  890. objc_setAssociatedObject(self, @selector(playingIndexPath), playingIndexPath, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  891. if (playingIndexPath) {
  892. // Stop the current playing cell video.
  893. [self stop];
  894. self.isSmallFloatViewShow = NO;
  895. if (self.smallFloatView) self.smallFloatView.hidden = YES;
  896. UIView *cell = [self.scrollView zf_getCellForIndexPath:playingIndexPath];
  897. self.containerView = [cell viewWithTag:self.containerViewTag];
  898. [self.orientationObserver cellModelRotateView:self.currentPlayerManager.view rotateViewAtCell:cell playerViewTag:self.containerViewTag];
  899. [self addDeviceOrientationObserver];
  900. self.scrollView.zf_playingIndexPath = playingIndexPath;
  901. [self layoutPlayerSubViews];
  902. } else {
  903. self.scrollView.zf_playingIndexPath = playingIndexPath;
  904. }
  905. }
  906. - (void)setShouldAutoPlay:(BOOL)shouldAutoPlay {
  907. objc_setAssociatedObject(self, @selector(shouldAutoPlay), @(shouldAutoPlay), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  908. self.scrollView.zf_shouldAutoPlay = shouldAutoPlay;
  909. }
  910. - (void)setSectionAssetURLs:(NSArray<NSArray<NSURL *> *> * _Nullable)sectionAssetURLs {
  911. objc_setAssociatedObject(self, @selector(sectionAssetURLs), sectionAssetURLs, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  912. }
  913. - (void)setPlayerDisapperaPercent:(CGFloat)playerDisapperaPercent {
  914. playerDisapperaPercent = MIN(MAX(0.0, playerDisapperaPercent), 1.0);
  915. self.scrollView.zf_playerDisapperaPercent = playerDisapperaPercent;
  916. objc_setAssociatedObject(self, @selector(playerDisapperaPercent), @(playerDisapperaPercent), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  917. }
  918. - (void)setPlayerApperaPercent:(CGFloat)playerApperaPercent {
  919. playerApperaPercent = MIN(MAX(0.0, playerApperaPercent), 1.0);
  920. self.scrollView.zf_playerApperaPercent = playerApperaPercent;
  921. objc_setAssociatedObject(self, @selector(playerApperaPercent), @(playerApperaPercent), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  922. }
  923. - (void)setZf_playerAppearingInScrollView:(void (^)(NSIndexPath * _Nonnull, CGFloat))zf_playerAppearingInScrollView {
  924. objc_setAssociatedObject(self, @selector(zf_playerAppearingInScrollView), zf_playerAppearingInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
  925. }
  926. - (void)setZf_playerDisappearingInScrollView:(void (^)(NSIndexPath * _Nonnull, CGFloat))zf_playerDisappearingInScrollView {
  927. objc_setAssociatedObject(self, @selector(zf_playerDisappearingInScrollView), zf_playerDisappearingInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
  928. }
  929. - (void)setZf_playerDidAppearInScrollView:(void (^)(NSIndexPath * _Nonnull))zf_playerDidAppearInScrollView {
  930. objc_setAssociatedObject(self, @selector(zf_playerDidAppearInScrollView), zf_playerDidAppearInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
  931. }
  932. - (void)setZf_playerWillDisappearInScrollView:(void (^)(NSIndexPath * _Nonnull))zf_playerWillDisappearInScrollView {
  933. objc_setAssociatedObject(self, @selector(zf_playerWillDisappearInScrollView), zf_playerWillDisappearInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
  934. }
  935. - (void)setZf_playerWillAppearInScrollView:(void (^)(NSIndexPath * _Nonnull))zf_playerWillAppearInScrollView {
  936. objc_setAssociatedObject(self, @selector(zf_playerWillAppearInScrollView), zf_playerWillAppearInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
  937. }
  938. - (void)setZf_playerDidDisappearInScrollView:(void (^)(NSIndexPath * _Nonnull))zf_playerDidDisappearInScrollView {
  939. objc_setAssociatedObject(self, @selector(zf_playerDidDisappearInScrollView), zf_playerDidDisappearInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
  940. }
  941. - (void)setZf_playerShouldPlayInScrollView:(void (^)(NSIndexPath * _Nonnull))zf_playerShouldPlayInScrollView {
  942. objc_setAssociatedObject(self, @selector(zf_playerShouldPlayInScrollView), zf_playerShouldPlayInScrollView, OBJC_ASSOCIATION_COPY_NONATOMIC);
  943. }
  944. - (void)setZf_scrollViewDidEndScrollingCallback:(void (^)(NSIndexPath * _Nonnull))zf_scrollViewDidEndScrollingCallback {
  945. objc_setAssociatedObject(self, @selector(zf_scrollViewDidEndScrollingCallback), zf_scrollViewDidEndScrollingCallback, OBJC_ASSOCIATION_COPY_NONATOMIC);
  946. }
  947. #pragma mark - getter
  948. - (UIScrollView *)scrollView {
  949. UIScrollView *scrollView = objc_getAssociatedObject(self, _cmd);
  950. return scrollView;
  951. }
  952. - (BOOL)isWWANAutoPlay {
  953. return [objc_getAssociatedObject(self, _cmd) boolValue];
  954. }
  955. - (BOOL)stopWhileNotVisible {
  956. NSNumber *number = objc_getAssociatedObject(self, _cmd);
  957. if (number) return number.boolValue;
  958. self.stopWhileNotVisible = YES;
  959. return YES;
  960. }
  961. - (NSInteger)containerViewTag {
  962. return [objc_getAssociatedObject(self, _cmd) integerValue];
  963. }
  964. - (NSIndexPath *)playingIndexPath {
  965. return objc_getAssociatedObject(self, _cmd);
  966. }
  967. - (NSIndexPath *)shouldPlayIndexPath {
  968. return self.scrollView.zf_shouldPlayIndexPath;
  969. }
  970. - (NSArray<NSArray<NSURL *> *> *)sectionAssetURLs {
  971. return objc_getAssociatedObject(self, _cmd);
  972. }
  973. - (BOOL)shouldAutoPlay {
  974. return [objc_getAssociatedObject(self, _cmd) boolValue];
  975. }
  976. - (CGFloat)playerDisapperaPercent {
  977. NSNumber *number = objc_getAssociatedObject(self, _cmd);
  978. if (number) return number.floatValue;
  979. self.playerDisapperaPercent = 0.5;
  980. return 0.5;
  981. }
  982. - (CGFloat)playerApperaPercent {
  983. NSNumber *number = objc_getAssociatedObject(self, _cmd);
  984. if (number) return number.floatValue;
  985. self.playerApperaPercent = 0.0;
  986. return 0.0;
  987. }
  988. - (void (^)(NSIndexPath * _Nonnull, CGFloat))zf_playerAppearingInScrollView {
  989. return objc_getAssociatedObject(self, _cmd);
  990. }
  991. - (void (^)(NSIndexPath * _Nonnull, CGFloat))zf_playerDisappearingInScrollView {
  992. return objc_getAssociatedObject(self, _cmd);
  993. }
  994. - (void (^)(NSIndexPath * _Nonnull))zf_playerDidAppearInScrollView {
  995. return objc_getAssociatedObject(self, _cmd);
  996. }
  997. - (void (^)(NSIndexPath * _Nonnull))zf_playerWillDisappearInScrollView {
  998. return objc_getAssociatedObject(self, _cmd);
  999. }
  1000. - (void (^)(NSIndexPath * _Nonnull))zf_playerWillAppearInScrollView {
  1001. return objc_getAssociatedObject(self, _cmd);
  1002. }
  1003. - (void (^)(NSIndexPath * _Nonnull))zf_playerDidDisappearInScrollView {
  1004. return objc_getAssociatedObject(self, _cmd);
  1005. }
  1006. - (void (^)(NSIndexPath * _Nonnull))zf_playerShouldPlayInScrollView {
  1007. return objc_getAssociatedObject(self, _cmd);
  1008. }
  1009. - (void (^)(NSIndexPath * _Nonnull))zf_scrollViewDidEndScrollingCallback {
  1010. return objc_getAssociatedObject(self, _cmd);
  1011. }
  1012. #pragma mark - Public method
  1013. - (void)zf_filterShouldPlayCellWhileScrolled:(void (^ __nullable)(NSIndexPath *indexPath))handler {
  1014. [self.scrollView zf_filterShouldPlayCellWhileScrolled:handler];
  1015. }
  1016. - (void)zf_filterShouldPlayCellWhileScrolling:(void (^ __nullable)(NSIndexPath *indexPath))handler {
  1017. [self.scrollView zf_filterShouldPlayCellWhileScrolling:handler];
  1018. }
  1019. - (void)playTheIndexPath:(NSIndexPath *)indexPath {
  1020. self.playingIndexPath = indexPath;
  1021. NSURL *assetURL;
  1022. if (self.sectionAssetURLs.count) {
  1023. assetURL = self.sectionAssetURLs[indexPath.section][indexPath.row];
  1024. } else if (self.assetURLs.count) {
  1025. assetURL = self.assetURLs[indexPath.row];
  1026. self.currentPlayIndex = indexPath.row;
  1027. }
  1028. self.assetURL = assetURL;
  1029. }
  1030. - (void)playTheIndexPath:(NSIndexPath *)indexPath scrollToTop:(BOOL)scrollToTop completionHandler:(void (^ _Nullable)(void))completionHandler {
  1031. NSURL *assetURL;
  1032. if (self.sectionAssetURLs.count) {
  1033. assetURL = self.sectionAssetURLs[indexPath.section][indexPath.row];
  1034. } else if (self.assetURLs.count) {
  1035. assetURL = self.assetURLs[indexPath.row];
  1036. self.currentPlayIndex = indexPath.row;
  1037. }
  1038. if (scrollToTop) {
  1039. @weakify(self)
  1040. [self.scrollView zf_scrollToRowAtIndexPath:indexPath completionHandler:^{
  1041. @strongify(self)
  1042. if (completionHandler) completionHandler();
  1043. self.playingIndexPath = indexPath;
  1044. self.assetURL = assetURL;
  1045. }];
  1046. } else {
  1047. if (completionHandler) completionHandler();
  1048. self.playingIndexPath = indexPath;
  1049. self.assetURL = assetURL;
  1050. }
  1051. }
  1052. - (void)playTheIndexPath:(NSIndexPath *)indexPath scrollToTop:(BOOL)scrollToTop {
  1053. if ([indexPath compare:self.playingIndexPath] == NSOrderedSame) return;
  1054. if (scrollToTop) {
  1055. @weakify(self)
  1056. [self.scrollView zf_scrollToRowAtIndexPath:indexPath completionHandler:^{
  1057. @strongify(self)
  1058. [self playTheIndexPath:indexPath];
  1059. }];
  1060. } else {
  1061. [self playTheIndexPath:indexPath];
  1062. }
  1063. }
  1064. - (void)playTheIndexPath:(NSIndexPath *)indexPath assetURL:(NSURL *)assetURL scrollToTop:(BOOL)scrollToTop {
  1065. self.playingIndexPath = indexPath;
  1066. self.assetURL = assetURL;
  1067. if (scrollToTop) {
  1068. [self.scrollView zf_scrollToRowAtIndexPath:indexPath completionHandler:nil];
  1069. }
  1070. }
  1071. @end
  1072. @implementation ZFPlayerController (ZFPlayerDeprecated)
  1073. - (void)updateScrollViewPlayerToCell {
  1074. if (self.currentPlayerManager.view && self.playingIndexPath && self.containerViewTag) {
  1075. UIView *cell = [self.scrollView zf_getCellForIndexPath:self.playingIndexPath];
  1076. self.containerView = [cell viewWithTag:self.containerViewTag];
  1077. [self.orientationObserver cellModelRotateView:self.currentPlayerManager.view rotateViewAtCell:cell playerViewTag:self.containerViewTag];
  1078. [self layoutPlayerSubViews];
  1079. }
  1080. }
  1081. - (void)updateNoramlPlayerWithContainerView:(UIView *)containerView {
  1082. if (self.currentPlayerManager.view && self.containerView) {
  1083. self.containerView = containerView;
  1084. [self.orientationObserver cellOtherModelRotateView:self.currentPlayerManager.view containerView:self.containerView];
  1085. [self layoutPlayerSubViews];
  1086. }
  1087. }
  1088. @end