AGPlayerView.m 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. #import "AGPlayerView.h"
  2. #import "NSString+time.h"
  3. #import "RotationScreen.h"
  4. #import "Masonry.h"
  5. #define RGBColor(r, g, b) [UIColor colorWithRed:r / 255.0 green:g / 255.0 blue:b / 255.0 alpha:1.0]
  6. static const NSTimeInterval kVideoPlayerAnimationTimeinterval = 0.3f;
  7. @interface AGPlayerView ()
  8. {
  9. BOOL _isIntoBackground; // 是否在后台
  10. BOOL _isShowToolbar; // 是否显示工具条
  11. BOOL _isSliding; // 是否正在滑动
  12. AVPlayerItem *_playerItem;
  13. AVPlayerLayer *_playerLayer;
  14. NSTimer *_timer;
  15. id _playTimeObserver; // 观察者
  16. CGRect _originFrame;
  17. }
  18. @property (weak, nonatomic) IBOutlet UIView *mainView;
  19. @property (weak, nonatomic) IBOutlet UIView *playerView;
  20. @property (weak, nonatomic) IBOutlet UIView *topView;
  21. @property (weak, nonatomic) IBOutlet UIButton *moreButton;
  22. @property (weak, nonatomic) IBOutlet UIView *downView;
  23. @property (weak, nonatomic) IBOutlet UIButton *playButton;
  24. @property (weak, nonatomic) IBOutlet UILabel *beginLabel;
  25. @property (weak, nonatomic) IBOutlet UILabel *endLabel;
  26. @property (weak, nonatomic) IBOutlet UISlider *playProgress;
  27. @property (weak, nonatomic) IBOutlet UIProgressView *loadedProgress; // 缓冲进度条
  28. @property (weak, nonatomic) IBOutlet UIButton *rotationButton;
  29. @property (weak, nonatomic) IBOutlet UIButton *playerButton;
  30. @property (weak, nonatomic) IBOutlet UIButton *playerFullScreenButton;
  31. @property (weak, nonatomic) IBOutlet UIView *inspectorView; // 继续播放/暂停播放
  32. @property (weak, nonatomic) IBOutlet UILabel *inspectorLabel; //
  33. // 约束动画
  34. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *topViewTop;
  35. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *downViewBottom;
  36. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *inspectorViewHeight;
  37. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *playProgressWidth;
  38. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *playerViewLeading;
  39. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *playerViewTrailing;
  40. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *playerViewAspect;
  41. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *backLeading;
  42. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *playLeading;
  43. @end
  44. @implementation AGPlayerView
  45. - (void)removeObserveAndNOtification {
  46. [_player replaceCurrentItemWithPlayerItem:nil];
  47. [_playerItem removeObserver:self forKeyPath:@"status"];
  48. [_playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
  49. [_player removeTimeObserver:_playTimeObserver];
  50. _playTimeObserver = nil;
  51. [[NSNotificationCenter defaultCenter] removeObserver:self];
  52. }
  53. - (instancetype)initWithFrame:(CGRect)frame{
  54. self = [super initWithFrame:frame];
  55. if (self) {
  56. //o 这里AGPlayerView。xib 实际是self。mainView。而不是self。改的别人代码有点乱(以后找时间重写吧,xib上面好多多余的元素,而且横屏机制不一样)
  57. // set
  58. self.mainView = [[[NSBundle mainBundle] loadNibNamed:@"AGPlayerView" owner:self options:nil] lastObject];
  59. self.mainView.frame = self.bounds;
  60. [self addSubview:self.mainView];
  61. self.playProgressWidth.constant = kSize.width - 200;
  62. // self.topViewTop.constant = _isLandscape ? 0 : (kStatusHeight-20);
  63. // setAVPlayer
  64. self.player = [[AVPlayer alloc] init];
  65. _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
  66. [self.playerView.layer addSublayer:_playerLayer];
  67. // bringFront
  68. [self.playerView bringSubviewToFront:_topView];
  69. [self.playerView bringSubviewToFront:_downView];
  70. [self.playerView bringSubviewToFront:_playerButton];
  71. [self.playerView bringSubviewToFront:_playProgress];
  72. //
  73. [self.playerView sendSubviewToBack:_inspectorView];
  74. // setPortraintLayout
  75. [self setPortarintLayout];
  76. // slider
  77. self.playProgress.value = 0.0;
  78. [self.playProgress setThumbImage:[UIImage imageNamed:@"icmpv_thumb_light"] forState:(UIControlStateNormal)];
  79. // 设置progress
  80. self.loadedProgress.progress = 0.0;
  81. // inspectorBackgroundColor
  82. self.inspectorView.backgroundColor = [RGBColor(203, 201, 204) colorWithAlphaComponent:0.5]; // 不影响子视图的透明度
  83. }
  84. return self;
  85. }
  86. #pragma mark-
  87. #pragma mark 横竖屏约束
  88. - (void)setPortarintLayout {
  89. _isLandscape = NO;
  90. // 不隐藏工具条
  91. [self portraitShow];
  92. // hideInspector
  93. self.inspectorViewHeight.constant = 0.0f;
  94. [self layoutIfNeeded];
  95. }
  96. // 显示工具条
  97. - (void)portraitShow {
  98. _isShowToolbar = YES; // 显示工具条置为 yes
  99. // 约束动画
  100. // self.topViewTop.constant = _isLandscape ? 0 : (kStatusHeight-20);
  101. self.downViewBottom.constant = 0;
  102. [UIView animateWithDuration:0.1 animations:^{
  103. [self layoutIfNeeded];
  104. self.topView.alpha = self.downView.alpha = 1;
  105. self.playerButton.alpha = self.playerFullScreenButton.alpha = 1;
  106. } completion:^(BOOL finished) {
  107. }];
  108. // 显示状态条 (暂时找不到替代方法,然后运行在ios11上又没有问题。所以先这样吧。。)
  109. [[UIApplication sharedApplication] setStatusBarHidden:NO animated:YES];
  110. [[UIApplication sharedApplication] setStatusBarStyle:(UIStatusBarStyleLightContent)];
  111. }
  112. - (void)portraitHide {
  113. _isShowToolbar = NO; // 显示工具条置为 no
  114. // 约束动画
  115. // self.topViewTop.constant = -(_isLandscape ? 0 : (kStatusHeight-20)+self.topView.frame.size.height);
  116. self.downViewBottom.constant = -(self.downView.frame.size.height);
  117. [UIView animateWithDuration:0.1 animations:^{
  118. [self layoutIfNeeded];
  119. self.topView.alpha = self.downView.alpha = 0;
  120. self.playerButton.alpha = self.playerFullScreenButton.alpha = 0;
  121. } completion:^(BOOL finished) {
  122. }];
  123. // 显示状态条
  124. [[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
  125. [[UIApplication sharedApplication] setStatusBarStyle:(UIStatusBarStyleLightContent)];
  126. }
  127. #pragma mark-
  128. #pragma mark inspectorView 动画
  129. - (void)inspectorViewShow {
  130. //
  131. [self.inspectorView.layer removeAllAnimations];
  132. // 更改文字
  133. if (_isPlaying) {
  134. self.inspectorLabel.text = @"继续播放";
  135. } else {
  136. self.inspectorLabel.text = @"暂停播放";
  137. }
  138. // 约束动画
  139. self.inspectorViewHeight.constant = 20.0f;
  140. [UIView animateWithDuration:0.3 animations:^{
  141. [self layoutIfNeeded];
  142. } completion:^(BOOL finished) {
  143. [self performSelector:@selector(inspectorViewHide) withObject:nil afterDelay:1]; // 0.2秒后隐藏
  144. }];
  145. }
  146. - (void)inspectorViewHide {
  147. self.inspectorViewHeight.constant = 0.0f;
  148. [UIView animateWithDuration:0.3 animations:^{
  149. [self layoutIfNeeded];
  150. } completion:^(BOOL finished) {
  151. }];
  152. }
  153. - (void)layoutSubviews {
  154. [super layoutSubviews];
  155. _playerLayer.frame = self.bounds;
  156. }
  157. #pragma mark- sizeClass 横竖屏约束
  158. // sizeClass 横竖屏切换时,执行
  159. - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
  160. [super traitCollectionDidChange:previousTraitCollection];
  161. // 横竖屏切换时重新添加约束
  162. CGRect bounds = self.bounds;
  163. [_mainView mas_remakeConstraints:^(MASConstraintMaker *make) {
  164. make.top.left.equalTo(@(0));
  165. make.width.equalTo(@(bounds.size.width));
  166. make.height.equalTo(@(bounds.size.height));
  167. }];
  168. // 横竖屏判断
  169. if (self.traitCollection.verticalSizeClass != UIUserInterfaceSizeClassCompact) { // 竖屏
  170. self.downView.backgroundColor = self.topView.backgroundColor = [UIColor clearColor];
  171. [self.rotationButton setImage:[UIImage imageNamed:@"player_fullScreen_iphone"] forState:(UIControlStateNormal)];
  172. } else { // 横屏
  173. self.downView.backgroundColor = self.topView.backgroundColor = RGBColor(89, 87, 90);
  174. [self.rotationButton setImage:[UIImage imageNamed:@"player_window_iphone"] forState:(UIControlStateNormal)];
  175. }
  176. // iPhone 6s 6 6sP 6p
  177. // 竖屏情况下 compact * regular compact * regular
  178. // 横屏情况下 compact * compact regular * compact
  179. // 以 verticalClass 来判断横竖屏
  180. // NSLog(@"horizontal %ld", (long)self.traitCollection.horizontalSizeClass);
  181. // NSLog(@"vertical %ld", (long)self.traitCollection.verticalSizeClass); //
  182. }
  183. #pragma mark-
  184. #pragma mark 横竖屏切换
  185. - (IBAction)rotationAction:(id)sender {
  186. if (_isLandscape) { // 如果是横屏,
  187. [RotationScreen forceOrientation:(UIInterfaceOrientationPortrait)]; // 切换为竖屏
  188. } else {
  189. [RotationScreen forceOrientation:(UIInterfaceOrientationLandscapeRight)]; // 否则,切换为横屏
  190. }
  191. //1点击-调屏幕转变调私有接口setOrientation,实际上因为没有配置general landscapeLeft/right 所以我们看见的屏幕不会变化。
  192. //2但是监听屏幕转变的方法又检测到屏幕方向变化。所以最后是在orientationHandler里面改变的我们看见的屏幕方向
  193. //3orientationHandler -> setIsLandscape
  194. //以上2,3当手机手动横置的时候也会触发 不过我没有细分左/右,只让他home在左了
  195. }
  196. /**
  197. * 屏幕旋转处理
  198. */
  199. - (void)orientationHandler {
  200. if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
  201. self.isLandscape = YES;
  202. }else if(UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) {
  203. self.isLandscape = NO;
  204. }else{
  205. //NSLog(@"我就看看有木有第三种");
  206. }
  207. }
  208. - (void)setIsLandscape:(BOOL)isLandscape {
  209. if (_isLandscape == isLandscape) {
  210. return;
  211. }
  212. _isLandscape = isLandscape;
  213. if (isLandscape) {
  214. _originFrame = self.frame;
  215. CGFloat height = kSize.width;
  216. CGFloat width = kSize.height;
  217. CGRect frame = CGRectMake((height - width) / 2, (width - height) / 2, width, height);
  218. if (is_iPhoneX) {
  219. self.playerViewLeading.constant = kStatusHeight;
  220. self.playerViewAspect.constant = kSize.width-(kSize.height-kStatusHeight-kSafeAreaBottomHeight)*14/25;
  221. }else{
  222. self.playerViewLeading.constant = 0;
  223. self.playLeading.constant = 40;
  224. self.backLeading.constant = 40;
  225. self.playerViewAspect.constant = kSize.width-(kSize.height-kSafeAreaBottomHeight)*14/25;
  226. }
  227. self.playerViewTrailing.constant = kSafeAreaBottomHeight;
  228. //以下2种方式无效,更新self.playerView约束
  229. // mas_remakeConstraints/mas_updateConstraints wuxiao
  230. self.playProgressWidth.constant = kSize.height - 200 - kStatusHeight-kSafeAreaBottomHeight;;
  231. [UIView animateWithDuration:kVideoPlayerAnimationTimeinterval animations:^{
  232. self.frame = frame;
  233. self.transform = CGAffineTransformMakeRotation(M_PI_2);
  234. [self.mainView mas_remakeConstraints:^(MASConstraintMaker *make) {
  235. make.top.left.equalTo(@(0));
  236. make.width.equalTo(@(kSize.height));
  237. make.height.equalTo(@(kSize.width));
  238. }];
  239. [self layoutIfNeeded];
  240. self.downView.backgroundColor = self.topView.backgroundColor = RGBColor(89, 87, 90);
  241. [self.rotationButton setImage:[UIImage imageNamed:@"player_window_iphone"] forState:(UIControlStateNormal)];
  242. } completion:^(BOOL finished) {}];
  243. }else {
  244. self.playLeading.constant = 12;
  245. self.backLeading.constant = 12;
  246. self.playerViewLeading.constant = 0;
  247. self.playerViewTrailing.constant = 0;
  248. self.playerViewAspect.constant = 0;
  249. self.playProgressWidth.constant = kSize.width - 200;;
  250. [UIView animateWithDuration:kVideoPlayerAnimationTimeinterval animations:^{
  251. self.transform = CGAffineTransformIdentity;
  252. self.frame = _originFrame;
  253. [self.mainView mas_remakeConstraints:^(MASConstraintMaker *make) {
  254. make.top.left.equalTo(@(0));
  255. make.width.equalTo(@(kSize.width));
  256. make.height.equalTo(@(self.bounds.size.height));
  257. }];
  258. [self layoutIfNeeded];
  259. self.downView.backgroundColor = self.topView.backgroundColor = [UIColor clearColor];
  260. [self.rotationButton setImage:[UIImage imageNamed:@"player_fullScreen_iphone"] forState:(UIControlStateNormal)];
  261. } completion:^(BOOL finished) {}];
  262. }
  263. }
  264. #pragma mark - 初始化playerItem
  265. - (void)updatePlayerWithURL:(NSURL *)url {
  266. NSLog(@"updatePlayerWithURL: %@",url);
  267. // 创建要播放的资源
  268. _playerItem = [[AVPlayerItem alloc]initWithURL:url];
  269. // 播放当前资源
  270. [self.player replaceCurrentItemWithPlayerItem:_playerItem];
  271. [self addObserverAndNotification]; // 添加观察者,发布通知
  272. }
  273. /**
  274. * 添加观察者 、通知 、监听播放进度
  275. */
  276. - (void)addObserverAndNotification {
  277. [_playerItem addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionNew) context:nil]; // 观察status属性, 一共有三种属性
  278. [_playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil]; // 观察缓冲进度
  279. [self monitoringPlayback:_playerItem]; // 监听播放
  280. [self addNotification]; // 添加通知
  281. }
  282. // 观察播放进度
  283. - (void)monitoringPlayback:(AVPlayerItem *)item {
  284. __weak typeof(self)WeakSelf = self;
  285. // 播放进度, 每秒执行30次, CMTime 为30分之一秒
  286. _playTimeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 30.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
  287. if (_touchMode != TouchPlayerViewModeHorizontal) {
  288. // 当前播放秒
  289. float currentPlayTime = (double)item.currentTime.value/ item.currentTime.timescale;
  290. // 更新slider, 如果正在滑动则不更新
  291. if (_isSliding == NO) {
  292. [WeakSelf updateVideoSlider:currentPlayTime];
  293. }
  294. } else {
  295. return;
  296. }
  297. }];
  298. }
  299. // 更新滑动条
  300. - (void)updateVideoSlider:(float)currentTime {
  301. self.playProgress.value = currentTime;
  302. self.beginLabel.text = [NSString convertTime:currentTime];
  303. }
  304. #pragma mark-
  305. #pragma mark 添加通知
  306. - (void)addNotification {
  307. //监听屏幕方向(这里没有在general里面配置landscape left/right 所以选择了这种方式)
  308. [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
  309. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationHandler) name:UIDeviceOrientationDidChangeNotification object:nil];
  310. // 播放完成通知
  311. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
  312. //程序到前台
  313. [[NSNotificationCenter defaultCenter] addObserver:self
  314. selector:@selector(applicationWillEnterForeground)
  315. name:UIApplicationWillEnterForegroundNotification
  316. object:nil];
  317. //程序到后台
  318. [[NSNotificationCenter defaultCenter] addObserver:self
  319. selector:@selector(applicationDidEnterBackground)
  320. name:UIApplicationDidEnterBackgroundNotification
  321. object:nil];
  322. //程序挂起
  323. [[NSNotificationCenter defaultCenter] addObserver:self
  324. selector:@selector(applicationWillResignActive)
  325. name:UIApplicationWillResignActiveNotification
  326. object:nil];
  327. //程序复原
  328. [[NSNotificationCenter defaultCenter] addObserver:self
  329. selector:@selector(applicationDidBecomeActive)
  330. name:UIApplicationDidBecomeActiveNotification
  331. object:nil];
  332. }
  333. - (void)playbackFinished:(NSNotification *)notification {
  334. NSLog(@"视频播放完成通知");
  335. [self pause];
  336. _playerItem = [notification object];
  337. // 是否无限循环
  338. [_playerItem seekToTime:kCMTimeZero]; // 跳转到初始
  339. // [_player play]; // 是否无限循环
  340. }
  341. /**
  342. * 程序到前台
  343. */
  344. - (void)applicationWillEnterForeground {
  345. NSLog(@"applicationWillEnterForeground-play");
  346. [self play];
  347. }
  348. /**
  349. * 程序进入后台
  350. */
  351. - (void)applicationDidEnterBackground {
  352. NSLog(@"applicationDidEnterBackground-pause");
  353. [self pause];
  354. }
  355. /**
  356. * 程序挂起
  357. */
  358. - (void)applicationWillResignActive {
  359. NSLog(@"applicationWillResignActive-pause");
  360. [self pause];
  361. }
  362. /**
  363. *程序复原
  364. */
  365. - (void)applicationDidBecomeActive
  366. {
  367. NSLog(@"applicationDidBecomeActive-play");
  368. [self play];
  369. }
  370. #pragma mark-
  371. #pragma mark KVO - status
  372. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
  373. AVPlayerItem *item = (AVPlayerItem *)object;
  374. if ([keyPath isEqualToString:@"status"]) {
  375. if (_isIntoBackground) {
  376. return;
  377. } else { // 判断status 的 状态
  378. AVPlayerStatus status = [[change objectForKey:@"new"] intValue]; // 获取更改后的状态
  379. if (status == AVPlayerStatusReadyToPlay) {
  380. NSLog(@"准备播放");
  381. // CMTime 本身是一个结构体
  382. CMTime duration = item.duration; // 获取视频长度
  383. NSLog(@"%.2f", CMTimeGetSeconds(duration));
  384. // 设置视频时间
  385. [self setMaxDuration:CMTimeGetSeconds(duration)];
  386. // 播放
  387. [self play];
  388. self.playButton.enabled = YES;
  389. self.playerButton.enabled = YES;
  390. self.playProgress.enabled = YES;
  391. } else if (status == AVPlayerStatusFailed) {
  392. NSLog(@"AVPlayerStatusFailed: %@",self.player.error.description);
  393. ShowMsg(@"播放失败,请退出重试");
  394. } else {
  395. NSLog(@"AVPlayerStatusUnknown");
  396. ShowMsg(@"未知错误");
  397. }
  398. }
  399. } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
  400. NSTimeInterval timeInterval = [self availableDurationRanges]; // 缓冲时间
  401. CGFloat totalDuration = CMTimeGetSeconds(_playerItem.duration); // 总时间
  402. [self.loadedProgress setProgress:timeInterval / totalDuration animated:YES];
  403. }
  404. }
  405. // 设置最大时间
  406. - (void)setMaxDuration:(CGFloat)duration {
  407. self.playProgress.maximumValue = duration; // maxValue = CMGetSecond(item.duration)
  408. self.endLabel.text = [NSString convertTime:duration];
  409. }
  410. // 已缓冲进度
  411. - (NSTimeInterval)availableDurationRanges {
  412. NSArray *loadedTimeRanges = [_playerItem loadedTimeRanges]; // 获取item的缓冲数组
  413. // discussion Returns an NSArray of NSValues containing CMTimeRanges
  414. // CMTimeRange 结构体 start duration 表示起始位置 和 持续时间
  415. CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue]; // 获取缓冲区域
  416. float startSeconds = CMTimeGetSeconds(timeRange.start);
  417. float durationSeconds = CMTimeGetSeconds(timeRange.duration);
  418. NSTimeInterval result = startSeconds + durationSeconds; // 计算总缓冲时间 = start + duration
  419. return result;
  420. }
  421. #pragma mark - 返回
  422. - (IBAction)goBackAction:(id)sender {
  423. if (self.goBackBlock) {
  424. self.goBackBlock();
  425. }
  426. }
  427. #pragma mark-
  428. #pragma mark 播放 暂停
  429. - (IBAction)playOrStopAction:(id)sender {
  430. if (_isPlaying) {
  431. [self pause];
  432. } else {
  433. [self play];
  434. }
  435. // inspectorAnimation
  436. [self inspectorViewShow];
  437. }
  438. - (void)play {
  439. NSLog(@"lee-play");
  440. _isPlaying = YES;
  441. [_player play]; // 调用avplayer 的play方法
  442. [self.playButton setImage:[UIImage imageNamed:@"Stop"] forState:(UIControlStateNormal)];
  443. [self.playerButton setImage:[UIImage imageNamed:@"player_pause_iphone_window"] forState:(UIControlStateNormal)];
  444. [self.playerFullScreenButton setImage:[UIImage imageNamed:@"player_pause_iphone_fullscreen"] forState:(UIControlStateNormal)];
  445. }
  446. - (void)pause {
  447. NSLog(@"lee-pause");
  448. _isPlaying = NO;
  449. [_player pause];
  450. [self.playButton setImage:[UIImage imageNamed:@"Play"] forState:(UIControlStateNormal)];
  451. [self.playerButton setImage:[UIImage imageNamed:@"player_start_iphone_window"] forState:(UIControlStateNormal)];
  452. [self.playerFullScreenButton setImage:[UIImage imageNamed:@"player_start_iphone_fullscreen"] forState:(UIControlStateNormal)];
  453. }
  454. #pragma mark-
  455. #pragma mark 处理点击事件
  456. - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  457. _touchMode = TouchPlayerViewModeNone;
  458. }
  459. //
  460. - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
  461. {
  462. if (_touchMode == TouchPlayerViewModeNone) {
  463. if (_isLandscape) { // 如果当前是横屏
  464. if (_isShowToolbar) {
  465. [self portraitHide];
  466. } else {
  467. [self portraitShow];
  468. }
  469. } else { // 如果是竖屏
  470. if (_isShowToolbar) {
  471. [self portraitHide];
  472. } else {
  473. [self portraitShow];
  474. }
  475. }
  476. }
  477. }
  478. //
  479. - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  480. }
  481. #pragma mark-
  482. #pragma mark 滑块事件
  483. - (IBAction)playerSliderTouchDown:(id)sender {
  484. [self pause];
  485. }
  486. - (IBAction)playerSliderTouchUpInside:(id)sender {
  487. _isSliding = NO; // 滑动结束
  488. [self play];
  489. }
  490. // 不要拖拽的时候改变, 手指抬起来后缓冲完成再改变
  491. - (IBAction)playerSliderValueChanged:(id)sender {
  492. _isSliding = YES;
  493. [self pause];
  494. CMTime changedTime = CMTimeMakeWithSeconds(self.playProgress.value, 1.0);
  495. // NSLog(@"%.2f", self.playProgress.value);
  496. [_playerItem seekToTime:changedTime completionHandler:^(BOOL finished) {
  497. // 跳转完成后做某事
  498. }];
  499. }
  500. @end