// // ALMoviePlayerControls.m // ALMoviePlayerController // // Created by Anthony Lobianco on 10/8/13. // Copyright (c) 2013 Anthony Lobianco. All rights reserved. // #import "ALMoviePlayerControls.h" #import "ALMoviePlayerController.h" #import "ALAirplayView.h" #import "ALButton.h" #import #import #import "SCGIFImageView.h" @implementation UIDevice (ALSystemVersion) + (float)iOSVersion { static float version = 0.f; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ version = [[[UIDevice currentDevice] systemVersion] floatValue]; }); return version; } @end @interface ALMoviePlayerControlsBar : UIView @property (nonatomic, strong) UIColor *color; @end static const inline BOOL isIpad() { return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad; } static const CGFloat activityIndicatorSize = 40.f; static const CGFloat iPhoneScreenPortraitWidth = 320.f; @interface ALMoviePlayerControls () { @private long windowSubviews; } @property (nonatomic, weak) ALMoviePlayerController *moviePlayer; @property (nonatomic, assign) ALMoviePlayerControlsState state; @property (nonatomic, getter = isShowing) BOOL showing; @property (nonatomic, strong) UIView *activityBackgroundView; @property (nonatomic, strong) UIActivityIndicatorView *activityIndicator; @property (nonatomic, strong) ALMoviePlayerControlsBar *topBar; @property (nonatomic, strong) ALMoviePlayerControlsBar *bottomBar; @property (nonatomic, strong) ALButton *playPauseButton; @property (nonatomic, strong) MPVolumeView *volumeView; @property (nonatomic, strong) ALAirplayView *airplayView; @property (nonatomic, strong) UILabel *timeElapsedLabel; @property (nonatomic, strong) UILabel *timeRemainingLabel; @property (nonatomic, strong) ALButton *seekForwardButton; @property (nonatomic, strong) ALButton *seekBackwardButton; @property (nonatomic, strong) ALButton *scaleButton; @property (nonatomic, strong) ALButton *closeButton; @end @implementation ALMoviePlayerControls # pragma mark - Construct/Destruct - (id)initWithMoviePlayer:(ALMoviePlayerController *)moviePlayer style:(ALMoviePlayerControlsStyle)style { self = [super init]; if (self) { self.backgroundColor = [UIColor clearColor]; _moviePlayer = moviePlayer; _style = style; _showing = NO; _fadeDelay = 5.0; _timeRemainingDecrements = NO; _barColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; //in fullscreen mode, move controls away from top status bar and bottom screen bezel. I think the iOS7 control center gestures interfere with the uibutton touch events. this will alleviate that a little (correct me if I'm wrong and/or adjust if necessary). _barHeight = [UIDevice iOSVersion] >= 7.0 ? 70.f : 50.f; _seekRate = 3.f; _state = ALMoviePlayerControlsStateIdle; [self setup]; [self addNotifications]; } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [_durationTimer invalidate]; [self nilDelegates]; } # pragma mark - Construct/Destruct Helpers - (void)setFrame:(CGRect)frame { [super setFrame:frame]; [self layoutSubviews]; } - (void)setup { if (self.style == ALMoviePlayerControlsStyleNone) return; //top bar _topBar = [[ALMoviePlayerControlsBar alloc] init]; _topBar.color = _barColor; _topBar.alpha = 0.f; [self addSubview:_topBar]; //bottom bar _bottomBar = [[ALMoviePlayerControlsBar alloc] init]; _bottomBar.color = _barColor; _bottomBar.alpha = 0.f; [self addSubview:_bottomBar]; _durationSlider = [[UISlider alloc] init]; _durationSlider.value = 0.f; _durationSlider.continuous = YES; [_durationSlider setThumbImage:Image(@"video/sliderThumb.png") forState:UIControlStateNormal]; [_durationSlider addTarget:self action:@selector(durationSliderValueChanged:) forControlEvents:UIControlEventValueChanged]; [_durationSlider addTarget:self action:@selector(durationSliderTouchBegan:) forControlEvents:UIControlEventTouchDown]; [_durationSlider addTarget:self action:@selector(durationSliderTouchEnded:) forControlEvents:UIControlEventTouchUpInside]; [_durationSlider addTarget:self action:@selector(durationSliderTouchEnded:) forControlEvents:UIControlEventTouchUpOutside]; _timeElapsedLabel = [[UILabel alloc] init]; _timeElapsedLabel.backgroundColor = [UIColor clearColor]; _timeElapsedLabel.font = appFont(11.f, NO); _timeElapsedLabel.textColor = [UIColor lightTextColor]; _timeElapsedLabel.textAlignment = NSTextAlignmentRight; _timeElapsedLabel.text = @"00:00"; _timeElapsedLabel.layer.shadowColor = [UIColor blackColor].CGColor; _timeElapsedLabel.layer.shadowRadius = 1.f; _timeElapsedLabel.layer.shadowOffset = CGSizeMake(1.f, 1.f); _timeElapsedLabel.layer.shadowOpacity = 0.8f; _timeRemainingLabel = [[UILabel alloc] init]; _timeRemainingLabel.backgroundColor = [UIColor clearColor]; _timeRemainingLabel.font = appFont(11.f, NO); _timeRemainingLabel.textColor = [UIColor lightTextColor]; _timeRemainingLabel.textAlignment = NSTextAlignmentRight; _timeRemainingLabel.text = @"/00:00"; _timeRemainingLabel.layer.shadowColor = [UIColor blackColor].CGColor; _timeRemainingLabel.layer.shadowRadius = 1.f; _timeRemainingLabel.layer.shadowOffset = CGSizeMake(1.f, 1.f); _timeRemainingLabel.layer.shadowOpacity = 0.8f; if (_style == ALMoviePlayerControlsStyleFullscreen || (_style == ALMoviePlayerControlsStyleDefault && _moviePlayer.isFullscreen)) { [_topBar addSubview:_durationSlider]; [_topBar addSubview:_timeElapsedLabel]; [_topBar addSubview:_timeRemainingLabel]; _fullscreenButton = [[ALButton alloc] init]; [_fullscreenButton setTitle:@"Done" forState:UIControlStateNormal]; [_fullscreenButton setTitleShadowColor:[UIColor blackColor] forState:UIControlStateNormal]; _fullscreenButton.titleLabel.shadowOffset = CGSizeMake(1.f, 1.f); [_fullscreenButton.titleLabel setFont:[UIFont systemFontOfSize:14.f]]; _fullscreenButton.delegate = self; [_fullscreenButton addTarget:self action:@selector(fullscreenPressed:) forControlEvents:UIControlEventTouchUpInside]; [_topBar addSubview:_fullscreenButton]; _scaleButton = [[ALButton alloc] init]; _scaleButton.delegate = self; [_scaleButton setImage:[UIImage imageNamed:@"movieFullscreen.png"] forState:UIControlStateNormal]; [_scaleButton setImage:[UIImage imageNamed:@"movieEndFullscreen.png"] forState:UIControlStateSelected]; [_scaleButton addTarget:self action:@selector(scalePressed:) forControlEvents:UIControlEventTouchUpInside]; [_topBar addSubview:_scaleButton]; _volumeView = [[MPVolumeView alloc] init]; [_volumeView setShowsRouteButton:NO]; [_volumeView setShowsVolumeSlider:YES]; [_bottomBar addSubview:_volumeView]; _seekForwardButton = [[ALButton alloc] init]; [_seekForwardButton setImage:[UIImage imageNamed:@"movieForward.png"] forState:UIControlStateNormal]; [_seekForwardButton setImage:[UIImage imageNamed:@"movieForwardSelected.png"] forState:UIControlStateSelected]; _seekForwardButton.delegate = self; [_seekForwardButton addTarget:self action:@selector(seekForwardPressed:) forControlEvents:UIControlEventTouchUpInside]; [_bottomBar addSubview:_seekForwardButton]; _seekBackwardButton = [[ALButton alloc] init]; [_seekBackwardButton setImage:[UIImage imageNamed:@"movieBackward.png"] forState:UIControlStateNormal]; [_seekBackwardButton setImage:[UIImage imageNamed:@"movieBackwardSelected.png"] forState:UIControlStateSelected]; _seekBackwardButton.delegate = self; [_seekBackwardButton addTarget:self action:@selector(seekBackwardPressed:) forControlEvents:UIControlEventTouchUpInside]; [_bottomBar addSubview:_seekBackwardButton]; } else if (_style == ALMoviePlayerControlsStyleEmbedded || (_style == ALMoviePlayerControlsStyleDefault && !_moviePlayer.isFullscreen)) { [_bottomBar addSubview:_durationSlider]; [_bottomBar addSubview:_timeElapsedLabel]; [_bottomBar addSubview:_timeRemainingLabel]; _fullscreenButton = [[ALButton alloc] init]; [_fullscreenButton setImage:Image(@"video/inFullScreen.png") forState:UIControlStateNormal]; [_fullscreenButton setImage:Image(@"video/outFullScreen.png") forState:UIControlStateSelected]; [_fullscreenButton addTarget:self action:@selector(fullscreenPressed:) forControlEvents:UIControlEventTouchUpInside]; _fullscreenButton.delegate = self; [_bottomBar addSubview:_fullscreenButton]; _closeButton = [[ALButton alloc]init]; [_closeButton setImage:Image(@"video/closeBtn.png") forState:UIControlStateNormal]; _closeButton.delegate = self; [_closeButton addTarget:self action:@selector(closeHandler:) forControlEvents:UIControlEventTouchUpInside]; _closeButton.alpha = 1.0f; /** * bug:0005018(iPhone6查看新闻内的视频时,没有用于退出视频的‘返回键’) */ [self addSubview:_closeButton]; } //static stuff _playPauseButton = [[ALButton alloc] init]; [_playPauseButton setImage:Image(@"video/pauseBtn.png") forState:UIControlStateNormal]; [_playPauseButton setImage:Image(@"video/playBtn.png") forState:UIControlStateSelected]; [_playPauseButton setSelected:_moviePlayer.playbackState == MPMoviePlaybackStatePlaying ? NO : YES]; [_playPauseButton addTarget:self action:@selector(playPausePressed:) forControlEvents:UIControlEventTouchUpInside]; _playPauseButton.delegate = self; [_bottomBar addSubview:_playPauseButton]; _airplayView = [[ALAirplayView alloc] init]; _airplayView.delegate = self; [_bottomBar addSubview:_airplayView]; _activityBackgroundView = [[UIView alloc] init]; [_activityBackgroundView setBackgroundColor:[UIColor blackColor]]; _activityBackgroundView.alpha = 0.f; _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; _activityIndicator.alpha = 0.f; _activityIndicator.hidesWhenStopped = YES; [self addSubview:self.cutPhotoBtn]; [self.cutPhotoBtn makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(self.right).offset(-12); make.centerY.equalTo(self); make.size.mas_equalTo(CGSizeMake(25, 25)); }]; } - (UIButton *)cutPhotoBtn { if (!_cutPhotoBtn) { _cutPhotoBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [_cutPhotoBtn setImage:Image(@"video/photoCut.png") forState:UIControlStateNormal]; self.cutPhotoBtn.hidden = YES; } return _cutPhotoBtn; } - (void)resetViews { [self stopDurationTimer]; [self nilDelegates]; [_activityBackgroundView removeFromSuperview]; [_activityIndicator removeFromSuperview]; [_topBar removeFromSuperview]; [_bottomBar removeFromSuperview]; } - (void)nilDelegates { _airplayView.delegate = nil; _playPauseButton.delegate = nil; _fullscreenButton.delegate = nil; _seekForwardButton.delegate = nil; _seekBackwardButton.delegate = nil; _scaleButton.delegate = nil; } # pragma mark - Setters - (void)setStyle:(ALMoviePlayerControlsStyle)style { if (_style != style) { BOOL flag = _style == ALMoviePlayerControlsStyleDefault; [self hideControls:^{ [self resetViews]; _style = style; [self setup]; if (_style != ALMoviePlayerControlsStyleNone) { double delayInSeconds = 0.2; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ [self setDurationSliderMaxMinValues]; [self monitorMoviePlayback]; //resume values [self startDurationTimer]; [self showControls:^{ if (flag) { //put style back to default _style = ALMoviePlayerControlsStyleDefault; } }]; }); } else { if (flag) { //put style back to default _style = ALMoviePlayerControlsStyleDefault; } } }]; } } - (void)setState:(ALMoviePlayerControlsState)state { if (_state != state) { _state = state; switch (state) { case ALMoviePlayerControlsStateLoading: [self showLoadingIndicators]; break; case ALMoviePlayerControlsStateReady: [self hideLoadingIndicators]; break; case ALMoviePlayerControlsStateIdle: default: break; } } } - (void)setBarColor:(UIColor *)barColor { if (_barColor != barColor) { _barColor = barColor; [self.topBar setColor:barColor]; [self.bottomBar setColor:barColor]; } } # pragma mark - UIControl/Touch Events - (void)durationSliderTouchBegan:(UISlider *)slider { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideControls:) object:nil]; [self.moviePlayer pause]; } - (void)durationSliderTouchEnded:(UISlider *)slider { double floorValue = floor(slider.value); [self.moviePlayer setCurrentPlaybackTime:floorValue]; [self.moviePlayer play]; [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } - (void)durationSliderValueChanged:(UISlider *)slider { double currentTime = floor(slider.value); double totalTime = floor(self.moviePlayer.duration); [self setTimeLabelValues:currentTime totalTime:totalTime]; } - (void)buttonTouchedDown:(UIButton *)button { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideControls:) object:nil]; } - (void)buttonTouchedUpOutside:(UIButton *)button { [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } - (void)buttonTouchCancelled:(UIButton *)button { [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } - (void)airplayButtonTouchedDown { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideControls:) object:nil]; } - (void)airplayButtonTouchedUpOutside { [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } - (void)airplayButtonTouchFailed { [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } - (void)airplayButtonTouchedUpInside { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideControls:) object:nil]; UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow]; if (!keyWindow) { keyWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:0]; } if (isIpad()) { windowSubviews = keyWindow.layer.sublayers.count; [keyWindow addObserver:self forKeyPath:@"layer.sublayers" options:NSKeyValueObservingOptionNew context:NULL]; } else { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeKey:) name:UIWindowDidBecomeKeyNotification object:nil]; } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (![keyPath isEqualToString:@"layer.sublayers"]) { return; } UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow]; if (!keyWindow) { keyWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:0]; } if (keyWindow.layer.sublayers.count == windowSubviews) { [keyWindow removeObserver:self forKeyPath:@"layer.sublayers"]; [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } } - (void)windowDidResignKey:(NSNotification *)note { UIWindow *resignedWindow = (UIWindow *)[note object]; if ([self isAirplayShowingInView:resignedWindow]) { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIWindowDidResignKeyNotification object:nil]; [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } } - (void)windowDidBecomeKey:(NSNotification *)note { UIWindow *keyWindow = (UIWindow *)[note object]; if ([self isAirplayShowingInView:keyWindow]) { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIWindowDidBecomeKeyNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidResignKey:) name:UIWindowDidResignKeyNotification object:nil]; } } - (BOOL)isAirplayShowingInView:(UIView *)view { BOOL actionSheet = NO; for (UIView *subview in view.subviews) { if ([subview isKindOfClass:[UIActionSheet class]]) { actionSheet = YES; } else { actionSheet = [self isAirplayShowingInView:subview]; } } return actionSheet; } - (void)playPausePressed:(UIButton *)button { self.moviePlayer.playbackState == MPMoviePlaybackStatePlaying ? [self.moviePlayer pause] : [self.moviePlayer play]; [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } - (void)closeHandler:(UIButton*)btn { if ([self.moviePlayer.delegate respondsToSelector:@selector(closeHandler)]) { [self.moviePlayer.delegate closeHandler]; } [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } - (void)fullscreenPressed:(UIButton *)button { button.selected = !button.selected; if (self.style == ALMoviePlayerControlsStyleDefault) { self.style = self.moviePlayer.isFullscreen; } // if (self.moviePlayer.currentPlaybackRate != 1.f) { // self.moviePlayer.currentPlaybackRate = 1.f; // } [self.moviePlayer setFullscreen:!self.moviePlayer.isFullscreen animated:YES]; [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } - (void)scalePressed:(UIButton *)button { button.selected = !button.selected; [self.moviePlayer setScalingMode:button.selected ? MPMovieScalingModeAspectFill : MPMovieScalingModeAspectFit]; } - (void)seekForwardPressed:(UIButton *)button { self.moviePlayer.currentPlaybackRate = !button.selected ? self.seekRate : 1.f; button.selected = !button.selected; self.seekBackwardButton.selected = NO; if (!button.selected) { [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } } - (void)seekBackwardPressed:(UIButton *)button { self.moviePlayer.currentPlaybackRate = !button.selected ? -self.seekRate : 1.f; button.selected = !button.selected; self.seekForwardButton.selected = NO; if (!button.selected) { [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if (self.style == ALMoviePlayerControlsStyleNone) return; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if (self.style == ALMoviePlayerControlsStyleNone) return; self.isShowing ? [self hideControls:nil] : [self showControls:nil]; } # pragma mark - Notifications - (void)addNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlaybackStateDidChange:) name:MPMoviePlayerPlaybackStateDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieContentURLDidChange:) name:ALMoviePlayerContentURLDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieDurationAvailable:) name:MPMovieDurationAvailableNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieLoadStateDidChange:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil]; } - (void)movieFinished:(NSNotification *)note { self.playPauseButton.selected = YES; [self.durationTimer invalidate]; [self.moviePlayer setCurrentPlaybackTime:0.0]; [self monitorMoviePlayback]; //reset values [self hideControls:nil]; self.state = ALMoviePlayerControlsStateIdle; } - (void)movieLoadStateDidChange:(NSNotification *)note { // NSLog(@"loadState:%ld",self.moviePlayer.loadState); switch (self.moviePlayer.loadState) { case MPMovieLoadStatePlayable: case MPMovieLoadStatePlaythroughOK: [self showControls:nil]; self.state = ALMoviePlayerControlsStateReady; break; case MPMovieLoadStateStalled: case MPMovieLoadStateUnknown: break; default: break; } } - (void)moviePlaybackStateDidChange:(NSNotification *)note { // NSLog(@"playbackState:%ld",self.moviePlayer.playbackState); switch (self.moviePlayer.playbackState) { case MPMoviePlaybackStatePlaying: self.playPauseButton.selected = NO; [self startDurationTimer]; //local file if ([self.moviePlayer.contentURL.scheme isEqualToString:@"file"]) { [self setDurationSliderMaxMinValues]; [self showControls:nil]; } if ([self.moviePlayer videoIsLiving]) { [self showControls:nil]; } case MPMoviePlaybackStateSeekingBackward: case MPMoviePlaybackStateSeekingForward: self.state = ALMoviePlayerControlsStateReady; break; case MPMoviePlaybackStateInterrupted: self.state = ALMoviePlayerControlsStateLoading; break; case MPMoviePlaybackStatePaused: case MPMoviePlaybackStateStopped: self.state = ALMoviePlayerControlsStateIdle; self.playPauseButton.selected = YES; [self stopDurationTimer]; break; default: break; } } - (void)movieDurationAvailable:(NSNotification *)note { [self setDurationSliderMaxMinValues]; } - (void)movieContentURLDidChange:(NSNotification *)note { [self hideControls:^{ //don't show loading indicator for local files self.state = [self.moviePlayer.contentURL.scheme isEqualToString:@"file"] ? ALMoviePlayerControlsStateReady : ALMoviePlayerControlsStateLoading; }]; } # pragma mark - Internal Methods - (void)startDurationTimer { self.durationTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(monitorMoviePlayback) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:self.durationTimer forMode:NSRunLoopCommonModes]; /** * bug:5825(视频:小屏播放视频时,在页面处拖动,视频时间不会走) */ } - (void)stopDurationTimer { [self.durationTimer invalidate]; } - (void)showControls:(void(^)(void))completion { // if ([self.moviePlayer videoIsLiving]) { // if (self.state == ALMoviePlayerControlsStateLoading) { // [self bringSubviewToFront:_activityBackgroundView]; // [self bringSubviewToFront:_activityIndicator]; // [self bringSubviewToFront:_closeButton]; // [UIView animateWithDuration:0.2f animations:^{ // _activityBackgroundView.alpha = 1.f; // _activityIndicator.alpha = 1.f; // }]; // return; // } // } if (!self.isShowing) { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideControls:) object:nil]; if (self.style == ALMoviePlayerControlsStyleFullscreen || (self.style == ALMoviePlayerControlsStyleDefault && self.moviePlayer.isFullscreen)) { [self.topBar setNeedsDisplay]; } [self.bottomBar setNeedsDisplay]; [UIView animateWithDuration:0.3 delay:0.0 options:0 animations:^{ if (self.style == ALMoviePlayerControlsStyleFullscreen || (self.style == ALMoviePlayerControlsStyleDefault && self.moviePlayer.isFullscreen)) { self.topBar.alpha = 1.f; } self.bottomBar.alpha = 1.f; self.cutPhotoBtn.alpha = 1.f; self.closeButton.alpha = 1.f; /** * bug:5350(视频:播放视频时,右上角的X也要超时后消失) */ } completion:^(BOOL finished) { _showing = YES; if (completion) completion(); [self performSelector:@selector(hideControls:) withObject:nil afterDelay:self.fadeDelay]; }]; } else { if (completion) completion(); } } - (void)hideControls:(void(^)(void))completion { if (self.isShowing) { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideControls:) object:nil]; [UIView animateWithDuration:0.3 delay:0.0 options:0 animations:^{ if (self.style == ALMoviePlayerControlsStyleFullscreen || (self.style == ALMoviePlayerControlsStyleDefault && self.moviePlayer.isFullscreen)) { self.topBar.alpha = 0.f; } self.bottomBar.alpha = 0.f; self.cutPhotoBtn.alpha = 0.f; self.closeButton.alpha = 0.f; } completion:^(BOOL finished) { _showing = NO; if (completion) completion(); }]; } else { if (completion) completion(); } } - (void)showLoadingIndicators { [self addSubview:_activityBackgroundView]; [self addSubview:_activityIndicator]; [self bringSubviewToFront:_activityBackgroundView]; [self bringSubviewToFront:_activityIndicator]; [_activityIndicator startAnimating]; _closeButton.alpha = 1.0; _closeButton.hidden = NO; [self bringSubviewToFront:_closeButton]; [UIView animateWithDuration:0.2f animations:^{ _activityBackgroundView.alpha = 1.f; _activityIndicator.alpha = 1.f; }]; } - (void)hideLoadingIndicators { [UIView animateWithDuration:0.2f delay:0.0 options:0 animations:^{ self.activityBackgroundView.alpha = 0.0f; self.activityIndicator.alpha = 0.f; } completion:^(BOOL finished) { [self.activityBackgroundView removeFromSuperview]; [self.activityIndicator removeFromSuperview]; }]; } - (void)setDurationSliderMaxMinValues { CGFloat duration = self.moviePlayer.duration; self.durationSlider.minimumValue = 0.f; self.durationSlider.maximumValue = duration; } - (void)setTimeLabelValues:(double)currentTime totalTime:(double)totalTime { // if ([self.moviePlayer videoIsLiving]) { // return; // } if ([self.moviePlayer videoIsLiving] && totalTime < 30) { self.timeElapsedLabel.text = @""; self.timeRemainingLabel.text = @"直播中"; [self layoutSubviews]; return; } double minutesElapsed = floor(currentTime / 60.0); double secondsElapsed = fmod(currentTime, 60.0); self.timeElapsedLabel.text = [NSString stringWithFormat:@"%02.0f:%02.0f/", minutesElapsed, secondsElapsed]; double minutesRemaining; double secondsRemaining; if (self.timeRemainingDecrements) { minutesRemaining = floor((totalTime - currentTime) / 60.0); secondsRemaining = fmod((totalTime - currentTime), 60.0); } else { minutesRemaining = floor(totalTime / 60.0); secondsRemaining = floor(fmod(totalTime, 60.0)); } self.timeRemainingLabel.text = self.timeRemainingDecrements ? [NSString stringWithFormat:@"-%02.0f:%02.0f", minutesRemaining, secondsRemaining] : [NSString stringWithFormat:@"%02.0f:%02.0f", minutesRemaining, secondsRemaining]; if (![self.timeRemainingLabel.text isEqualToString:@"00:00"]) { if (!self.durationSlider.enabled) { self.durationSlider.enabled = YES; } } if (currentTime == 0) { [self layoutSubviews]; } } - (void)monitorMoviePlayback { double currentTime = floor(self.moviePlayer.currentPlaybackTime); double totalTime = floor(self.moviePlayer.duration); [self setTimeLabelValues:currentTime totalTime:totalTime]; if (totalTime<10 && [self.moviePlayer videoIsLiving]) { return; } self.durationSlider.value = ceil(currentTime); } - (void)layoutSubviews { if (isIOS7) { if (self.airplayView.wirelessRoutesAvailable) { self.airplayView.hidden = NO; }else { self.airplayView.hidden = YES; } } if (self.style == ALMoviePlayerControlsStyleNone) return; //common sizes CGFloat paddingFromBezel = self.frame.size.width <= iPhoneScreenPortraitWidth ? 10.f : 20.f; CGFloat paddingBetweenButtons = self.frame.size.width <= iPhoneScreenPortraitWidth ? 10.f : 30.f; CGFloat paddingBetweenPlaybackButtons = self.frame.size.width <= iPhoneScreenPortraitWidth ? 20.f : 30.f; CGFloat paddingBetweenLabelsAndSlider = 10.f; CGFloat sliderHeight = 34.f; //default height CGFloat volumeHeight = 20.f; CGFloat volumeWidth = isIpad() ? 210.f : 120.f; CGFloat seekWidth = 36.f; CGFloat seekHeight = 20.f; CGFloat airplayWidth = 30.f; CGFloat airplayHeight = 22.f; CGFloat playWidth = 18.f; CGFloat playHeight = 20.f; CGFloat labelWidth = 40.f; if (self.style == ALMoviePlayerControlsStyleFullscreen || (self.style == ALMoviePlayerControlsStyleDefault && self.moviePlayer.isFullscreen)) { //top bar CGFloat fullscreenWidth = 34.f; CGFloat fullscreenHeight = self.barHeight; CGFloat scaleWidth = 28.f; CGFloat scaleHeight = 28.f; self.topBar.frame = CGRectMake(0, 0, self.frame.size.width, self.barHeight); self.fullscreenButton.frame = CGRectMake(paddingFromBezel, self.barHeight/2 - fullscreenHeight/2, fullscreenWidth, fullscreenHeight); self.timeElapsedLabel.frame = CGRectMake(self.fullscreenButton.frame.origin.x + self.fullscreenButton.frame.size.width + paddingBetweenButtons, 0, labelWidth, self.barHeight); self.scaleButton.frame = CGRectMake(self.topBar.frame.size.width - paddingFromBezel - scaleWidth, self.barHeight/2 - scaleHeight/2, scaleWidth, scaleHeight); self.timeRemainingLabel.frame = CGRectMake(self.scaleButton.frame.origin.x - paddingBetweenButtons - labelWidth, 0, labelWidth, self.barHeight); //bottom bar self.bottomBar.frame = CGRectMake(0, self.frame.size.height - self.barHeight, self.frame.size.width, self.barHeight); self.playPauseButton.frame = CGRectMake(self.bottomBar.frame.size.width/2 - playWidth/2, self.barHeight/2 - playHeight/2, playWidth, playHeight); self.seekForwardButton.frame = CGRectMake(self.playPauseButton.frame.origin.x + self.playPauseButton.frame.size.width + paddingBetweenPlaybackButtons, self.barHeight/2 - seekHeight/2 + 1.f, seekWidth, seekHeight); self.seekBackwardButton.frame = CGRectMake(self.playPauseButton.frame.origin.x - paddingBetweenPlaybackButtons - seekWidth, self.barHeight/2 - seekHeight/2 + 1.f, seekWidth, seekHeight); //hide volume view in iPhone's portrait orientation if (self.frame.size.width <= iPhoneScreenPortraitWidth) { self.volumeView.alpha = 0.f; } else { self.volumeView.alpha = 1.f; self.volumeView.frame = CGRectMake(paddingFromBezel, self.barHeight/2 - volumeHeight/2, volumeWidth, volumeHeight); } self.airplayView.frame = CGRectMake(self.bottomBar.frame.size.width - paddingFromBezel - airplayWidth, self.barHeight/2 - airplayHeight/2, airplayWidth, airplayHeight); self.airplayView.hidden = YES; } else if (self.style == ALMoviePlayerControlsStyleEmbedded || (self.style == ALMoviePlayerControlsStyleDefault && !self.moviePlayer.isFullscreen)) { self.bottomBar.frame = CGRectMake(0, self.frame.size.height - self.barHeight, self.frame.size.width, self.barHeight); //left side of bottom bar self.playPauseButton.frame = CGRectMake(10, self.barHeight/2 - playHeight/2, playWidth, playHeight); //right side of bottom bar CGFloat fullscreenWidth = 28.f; CGFloat fullscreenHeight = fullscreenWidth; self.fullscreenButton.frame = CGRectMake(self.bottomBar.frame.size.width - 10 - fullscreenWidth, self.barHeight/2 - fullscreenHeight/2, fullscreenWidth, fullscreenHeight); if (self.moviePlayer.isFullscreen) { self.airplayView.frame = CGRectMake(self.fullscreenButton.frame.origin.x - 10 - airplayWidth, self.barHeight/2 - airplayHeight/2, airplayWidth, airplayHeight); self.airplayView.hidden = YES; self.closeButton.hidden = NO; }else { self.airplayView.frame = CGRectMake(self.fullscreenButton.frame.origin.x - 5 - airplayWidth, self.barHeight/2 - airplayHeight/2, airplayWidth, airplayHeight); self.closeButton.hidden = NO; } CGFloat orginRemainX = 0; if (self.airplayView.hidden) { orginRemainX = self.fullscreenButton.frame.origin.x; }else { orginRemainX = self.airplayView.frame.origin.x; } CGFloat timeRemainingLabelWidth = widthForString(self.timeRemainingLabel.text, self.timeRemainingLabel.font, self.barHeight/2, self.timeRemainingLabel.lineBreakMode); self.timeRemainingLabel.frame = CGRectMake(orginRemainX - timeRemainingLabelWidth - paddingBetweenLabelsAndSlider, self.barHeight/2, timeRemainingLabelWidth, self.barHeight/2); CGFloat timeElapsedLabelWidth = 45; self.timeElapsedLabel.frame = CGRectMake(self.timeRemainingLabel.frame.origin.x - timeElapsedLabelWidth , self.barHeight/2, timeElapsedLabelWidth, self.barHeight/2); /** * bug:5573(视频:全屏播放视频,在体统字体下底部的时间显示有缺失) */ } self.closeButton.frame = CGRectMake(self.frame.size.width - 41/2-10, 10, 41/2, 41/2); //duration slider CGFloat playPauseX = self.playPauseButton.frame.origin.x; CGFloat airplayViewX = self.airplayView.frame.origin.x; if (self.airplayView.hidden) { airplayViewX = self.fullscreenButton.frame.origin.x; }else { airplayViewX = self.airplayView.frame.origin.x; } CGFloat sliderWidth = ((airplayViewX - paddingBetweenLabelsAndSlider) - (playPauseX + self.playPauseButton.frame.size.width + paddingBetweenLabelsAndSlider)); self.durationSlider.frame = CGRectMake(playPauseX + self.playPauseButton.frame.size.width + paddingBetweenLabelsAndSlider, self.barHeight/2 - sliderHeight/2, sliderWidth, sliderHeight); if (self.state == ALMoviePlayerControlsStateLoading) { [_activityBackgroundView setFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; [_activityIndicator setFrame:CGRectMake((self.frame.size.width / 2) - (activityIndicatorSize / 2), (self.frame.size.height / 2) - (activityIndicatorSize / 2), activityIndicatorSize, activityIndicatorSize)]; } [super layoutSubviews]; } @end # pragma mark - ALMoviePlayerControlsBar @implementation ALMoviePlayerControlsBar - (id)init { if ( self = [super init] ) { self.opaque = NO; } return self; } - (void)setColor:(UIColor *)color { if (_color != color) { _color = color; [self setNeedsDisplay]; } } - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, [_color CGColor]); CGContextFillRect(context, rect); } @end