TZVideoPlayerController.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //
  2. // TZVideoPlayerController.m
  3. // TZImagePickerController
  4. //
  5. // Created by 谭真 on 16/1/5.
  6. // Copyright © 2016年 谭真. All rights reserved.
  7. //
  8. #import "TZVideoPlayerController.h"
  9. #import <MediaPlayer/MediaPlayer.h>
  10. #import "UIView+Layout.h"
  11. #import "TZImageManager.h"
  12. #import "TZAssetModel.h"
  13. #import "TZImagePickerController.h"
  14. #import "TZPhotoPreviewController.h"
  15. @interface TZVideoPlayerController () {
  16. AVPlayer *_player;
  17. AVPlayerLayer *_playerLayer;
  18. UIButton *_playButton;
  19. UIImage *_cover;
  20. UIView *_toolBar;
  21. UIButton *_doneButton;
  22. UIProgressView *_progress;
  23. UIStatusBarStyle _originStatusBarStyle;
  24. }
  25. @property (assign, nonatomic) BOOL needShowStatusBar;
  26. // iCloud无法同步提示UI
  27. @property (nonatomic, strong) UIView *iCloudErrorView;
  28. @end
  29. #pragma clang diagnostic push
  30. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  31. @implementation TZVideoPlayerController
  32. - (void)viewDidLoad {
  33. [super viewDidLoad];
  34. self.needShowStatusBar = ![UIApplication sharedApplication].statusBarHidden;
  35. self.view.backgroundColor = [UIColor blackColor];
  36. TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  37. if (tzImagePickerVc) {
  38. self.navigationItem.title = tzImagePickerVc.previewBtnTitleStr;
  39. }
  40. [self configMoviePlayer];
  41. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerAndShowNaviBar) name:UIApplicationWillResignActiveNotification object:nil];
  42. }
  43. - (void)viewWillAppear:(BOOL)animated {
  44. [super viewWillAppear:animated];
  45. _originStatusBarStyle = [UIApplication sharedApplication].statusBarStyle;
  46. [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
  47. }
  48. - (void)viewWillDisappear:(BOOL)animated {
  49. [super viewWillDisappear:animated];
  50. if (self.needShowStatusBar) {
  51. [UIApplication sharedApplication].statusBarHidden = NO;
  52. }
  53. [UIApplication sharedApplication].statusBarStyle = _originStatusBarStyle;
  54. }
  55. - (void)configMoviePlayer {
  56. [[TZImageManager manager] getPhotoWithAsset:_model.asset completion:^(UIImage *photo, NSDictionary *info, BOOL isDegraded) {
  57. BOOL iCloudSyncFailed = !photo && [TZCommonTools isICloudSyncError:info[PHImageErrorKey]];
  58. self.iCloudErrorView.hidden = !iCloudSyncFailed;
  59. if (!isDegraded && photo) {
  60. self->_cover = photo;
  61. self->_doneButton.enabled = YES;
  62. }
  63. }];
  64. [[TZImageManager manager] getVideoWithAsset:_model.asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) {
  65. dispatch_async(dispatch_get_main_queue(), ^{
  66. self->_player = [AVPlayer playerWithPlayerItem:playerItem];
  67. self->_playerLayer = [AVPlayerLayer playerLayerWithPlayer:self->_player];
  68. self->_playerLayer.frame = self.view.bounds;
  69. [self.view.layer addSublayer:self->_playerLayer];
  70. [self addProgressObserver];
  71. [self configPlayButton];
  72. [self configBottomToolBar];
  73. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pausePlayerAndShowNaviBar) name:AVPlayerItemDidPlayToEndTimeNotification object:self->_player.currentItem];
  74. });
  75. }];
  76. }
  77. /// Show progress,do it next time / 给播放器添加进度更新,下次加上
  78. - (void)addProgressObserver{
  79. AVPlayerItem *playerItem = _player.currentItem;
  80. UIProgressView *progress = _progress;
  81. [_player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
  82. float current = CMTimeGetSeconds(time);
  83. float total = CMTimeGetSeconds([playerItem duration]);
  84. if (current) {
  85. [progress setProgress:(current/total) animated:YES];
  86. }
  87. }];
  88. }
  89. - (void)configPlayButton {
  90. _playButton = [UIButton buttonWithType:UIButtonTypeCustom];
  91. [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal];
  92. [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlayHL"] forState:UIControlStateHighlighted];
  93. [_playButton addTarget:self action:@selector(playButtonClick) forControlEvents:UIControlEventTouchUpInside];
  94. [self.view addSubview:_playButton];
  95. }
  96. - (void)configBottomToolBar {
  97. _toolBar = [[UIView alloc] initWithFrame:CGRectZero];
  98. CGFloat rgb = 34 / 255.0;
  99. _toolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:0.7];
  100. _doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
  101. _doneButton.titleLabel.font = [UIFont systemFontOfSize:16];
  102. if (!_cover) {
  103. _doneButton.enabled = NO;
  104. }
  105. [_doneButton addTarget:self action:@selector(doneButtonClick) forControlEvents:UIControlEventTouchUpInside];
  106. TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  107. if (tzImagePickerVc) {
  108. [_doneButton setTitle:tzImagePickerVc.doneBtnTitleStr forState:UIControlStateNormal];
  109. [_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal];
  110. } else {
  111. [_doneButton setTitle:[NSBundle tz_localizedStringForKey:@"Done"] forState:UIControlStateNormal];
  112. [_doneButton setTitleColor:[UIColor colorWithRed:(83/255.0) green:(179/255.0) blue:(17/255.0) alpha:1.0] forState:UIControlStateNormal];
  113. }
  114. [_doneButton setTitleColor:tzImagePickerVc.oKButtonTitleColorDisabled forState:UIControlStateDisabled];
  115. [_toolBar addSubview:_doneButton];
  116. [self.view addSubview:_toolBar];
  117. if (tzImagePickerVc.videoPreviewPageUIConfigBlock) {
  118. tzImagePickerVc.videoPreviewPageUIConfigBlock(_playButton, _toolBar, _doneButton);
  119. }
  120. }
  121. - (UIStatusBarStyle)preferredStatusBarStyle {
  122. TZImagePickerController *tzImagePicker = (TZImagePickerController *)self.navigationController;
  123. if (tzImagePicker && [tzImagePicker isKindOfClass:[TZImagePickerController class]]) {
  124. return tzImagePicker.statusBarStyle;
  125. }
  126. return [super preferredStatusBarStyle];
  127. }
  128. #pragma mark - Layout
  129. - (void)viewDidLayoutSubviews {
  130. [super viewDidLayoutSubviews];
  131. BOOL isFullScreen = self.view.tz_height == [UIScreen mainScreen].bounds.size.height;
  132. CGFloat statusBarHeight = isFullScreen ? [TZCommonTools tz_statusBarHeight] : 0;
  133. CGFloat statusBarAndNaviBarHeight = statusBarHeight + self.navigationController.navigationBar.tz_height;
  134. _playerLayer.frame = self.view.bounds;
  135. CGFloat toolBarHeight = [TZCommonTools tz_isIPhoneX] ? 44 + (83 - 49) : 44;
  136. _toolBar.frame = CGRectMake(0, self.view.tz_height - toolBarHeight, self.view.tz_width, toolBarHeight);
  137. _doneButton.frame = CGRectMake(self.view.tz_width - 44 - 12, 0, 44, 44);
  138. _playButton.frame = CGRectMake(0, statusBarAndNaviBarHeight, self.view.tz_width, self.view.tz_height - statusBarAndNaviBarHeight - toolBarHeight);
  139. TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  140. if (tzImagePickerVc.videoPreviewPageDidLayoutSubviewsBlock) {
  141. tzImagePickerVc.videoPreviewPageDidLayoutSubviewsBlock(_playButton, _toolBar, _doneButton);
  142. }
  143. }
  144. #pragma mark - Click Event
  145. - (void)playButtonClick {
  146. CMTime currentTime = _player.currentItem.currentTime;
  147. CMTime durationTime = _player.currentItem.duration;
  148. if (_player.rate == 0.0f) {
  149. if (currentTime.value == durationTime.value) [_player.currentItem seekToTime:CMTimeMake(0, 1)];
  150. [_player play];
  151. [self.navigationController setNavigationBarHidden:YES];
  152. _toolBar.hidden = YES;
  153. [_playButton setImage:nil forState:UIControlStateNormal];
  154. [UIApplication sharedApplication].statusBarHidden = YES;
  155. } else {
  156. [self pausePlayerAndShowNaviBar];
  157. }
  158. }
  159. - (void)doneButtonClick {
  160. if (self.navigationController) {
  161. TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
  162. if (imagePickerVc.autoDismiss) {
  163. [self.navigationController dismissViewControllerAnimated:YES completion:^{
  164. [self callDelegateMethod];
  165. }];
  166. } else {
  167. [self callDelegateMethod];
  168. }
  169. } else {
  170. [self dismissViewControllerAnimated:YES completion:^{
  171. [self callDelegateMethod];
  172. }];
  173. }
  174. }
  175. - (void)callDelegateMethod {
  176. TZImagePickerController *imagePickerVc = (TZImagePickerController *)self.navigationController;
  177. if ([imagePickerVc.pickerDelegate respondsToSelector:@selector(imagePickerController:didFinishPickingVideo:sourceAssets:)]) {
  178. [imagePickerVc.pickerDelegate imagePickerController:imagePickerVc didFinishPickingVideo:_cover sourceAssets:_model.asset];
  179. }
  180. if (imagePickerVc.didFinishPickingVideoHandle) {
  181. imagePickerVc.didFinishPickingVideoHandle(_cover,_model.asset);
  182. }
  183. }
  184. #pragma mark - Notification Method
  185. - (void)pausePlayerAndShowNaviBar {
  186. [_player pause];
  187. _toolBar.hidden = NO;
  188. [self.navigationController setNavigationBarHidden:NO];
  189. [_playButton setImage:[UIImage tz_imageNamedFromMyBundle:@"MMVideoPreviewPlay"] forState:UIControlStateNormal];
  190. if (self.needShowStatusBar) {
  191. [UIApplication sharedApplication].statusBarHidden = NO;
  192. }
  193. }
  194. #pragma mark - lazy
  195. - (UIView *)iCloudErrorView{
  196. if (!_iCloudErrorView) {
  197. _iCloudErrorView = [[UIView alloc] initWithFrame:CGRectMake(0, [TZCommonTools tz_isIPhoneX] ? 88 + 10 : 64 + 10, self.view.tz_width, 28)];
  198. UIImageView *icloud = [[UIImageView alloc] init];
  199. icloud.image = [UIImage tz_imageNamedFromMyBundle:@"iCloudError"];
  200. icloud.frame = CGRectMake(20, 0, 28, 28);
  201. [_iCloudErrorView addSubview:icloud];
  202. UILabel *label = [[UILabel alloc] init];
  203. label.frame = CGRectMake(53, 0, self.view.tz_width - 63, 28);
  204. label.font = [UIFont systemFontOfSize:10];
  205. label.textColor = [UIColor whiteColor];
  206. label.text = [NSBundle tz_localizedStringForKey:@"iCloud sync failed"];
  207. [_iCloudErrorView addSubview:label];
  208. [self.view addSubview:_iCloudErrorView];
  209. _iCloudErrorView.hidden = YES;
  210. }
  211. return _iCloudErrorView;
  212. }
  213. - (void)dealloc {
  214. [[NSNotificationCenter defaultCenter] removeObserver:self];
  215. }
  216. #pragma clang diagnostic pop
  217. @end