How to custom a IOS movie player control bar
To custom a ISO player control bar, you should create a subclass of MPMoviePlayerViewController. If you use MPMoviePlayerController, there is no root view to add a custome view layer. Also, if you want to set movie player’s initial orientation, you must use a subclass of MPMoviePlayerViewController.
The first step is removing the original control bar, you can use
[self.movieplayer setControlStyle:MPMovieControleStyleNone];
and create a custom control bar. the structure is shown as below:
Design
Create a good User-experience player control bar, you should consider following components and functional features:
Components
movie title Label
show movie basic information such as title.
Play/Pause Button
play or stop playing movies.
Back Button
return to previous page
Player Slider
show current play rate, and can seek to specified position.
Current/full Time Label
show playing movie status.
setting selector
give options for user to change movie related characters such as “audio”, “subtitle”, “resolution”.
Note: Because player control bar‘s position should not hinder watching movie. we separate all components into top and bottom of the view to show control bar.
Top Bar
back button | movie title label | setting button(optional)
Bottom Bar
player Slider | current/full time label
Note: Play/pause button was shown in center of the view.
Component Declaration
@interface MyMoviePlayerViewController()
{
UIButton *centerButton; // play|pause button.
UIButton *backButton;
UIButton *settingButton; // optional
UISlider *playerSlider;
UIView *playerControlView; // trigger control bar show and hide
UIView *playerSettingView; // optional,refer to settng button.
UILabel *currentTimeLabel;
UILabel *endTimeLabel;
float landScapeScreenWidth;
float landScapeScreenHeight;
NSTimer *timer ; // this timer is used for updating "current Time" and "player slider".
NSTimer *subtitleTimer;
NSTimer *autohide; // auto hide control bar after losing user focus.
UIView *topbarBG;
UIView *bottombarBG;
UIImageView *subtitleView;
UIActivityIndicatorView *loadingButton;
BOOL isinit;
NSMutableDictionary *subtitleArray;
NSMutableArray *currentSubtitle;
double lastControlTime;
UITapGestureRecognizer *tapGesture; // detect touch event on player control
UITapGestureRecognizer *tapGesture2; // detect touch event on player slider bar
NSString *subtitleLanguage;
NSTimeInterval lastViewTime;
int initX;
int initY;
}
Features
control bar show/hide
control bar can auto hide in 5 seconds after losing user’s focus
source Code:
autohide = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(autoHidePlayerControl) userInfo:nil repeats:YES];
-(void)autoHidePlayerControl
{
float duration = CFAbsoluteTimeGetCurrent() - lastControlTime; // lastControlTime records latest operation time
NSLog(@"%f",duration);
if(isControlViewShowed && duration> 5){ // 5 seconds remain time before hiding it
[UIView animateWithDuration:0.5 animations:^{
[self hidePlayerControl];
isControlViewShowed = NO;
}];
}
}
current play Time update
update real playing time per second.
source code:
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateSlider) userInfo:nil repeats:YES];
-(void)updateSlider {
if(!isSilderTouched){
float value = self.moviePlayer.currentPlaybackTime/self.moviePlayer.duration;
[playerSlider setValue: value animated:YES];
currentTimeLabel.text = [self secondsToMMSS:self.moviePlayer.currentPlaybackTime];
}
}
-(NSString *)secondsToMMSS:(double)seconds //transfor min-seconds to H:MM:SS
{
NSInteger time = floor(seconds);
NSInteger hh = time / 3600;
NSInteger mm = (time / 60) % 60;
NSInteger ss = time % 60;
if(hh > 0)
return [NSString stringWithFormat:@"%d:%02i:%02i",hh,mm,ss];
else
return [NSString stringWithFormat:@"%02i:%02i",mm,ss];
}
player slider control
playerSlider = [[UISlider alloc] init];
[playerSlider setContinuous:YES];
[playerSlider setHighlighted:YES];
// remove the slider filling default blue color
[playerSlider setMaximumTrackTintColor:[UIColor colorWithRed:193.0f/255.0f green:193.0f/255.0f blue:193.0f/255.0f alpha:1]];
[playerSlider setMinimumTrackTintColor:[UIColor colorWithRed:11.0f/255.0f green:156.0f/255.0f blue:231.0f/255.0f alpha:1]];
playerSlider.frame = CGRectMake(landScapeScreenWidth*0.1f, 0, landScapeScreenWidth*0.8f , 22);
Two ways to seek movies:
A. draging slider bar’s thumb
[playerSlider addTarget:self action:@selector(sliderMoveStart) forControlEvents:UIControlEventTouchDown];
[playerSlider addTarget:self action:@selector(sliderMoving) forControlEvents:UIControlEventTouchDragInside];
[playerSlider addTarget:self action:@selector(sliderMoveEnd) forControlEvents:UIControlEventTouchUpInside];
-(void)sliderMoveStart{
isSilderTouched = YES;
}
-(void)sliderMoving{
lastControlTime = CFAbsoluteTimeGetCurrent();
isSilderTouched = YES;
double time = self.moviePlayer.duration * playerSlider.value;
currentTimeLabel.text = [self secondsToMMSS:time]; //
}
-(void)sliderMoveEnd
{
self.moviePlayer.currentPlaybackTime = self.moviePlayer.duration * playerSlider.value;
}
B. click slider bar
-(void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
NSLog(@"%@",recognizer.view.class.description);
if(recognizer.view == playerControlView){
NSLog(@"CONTROLVIEW CLICKED");
if(isControlViewShowed){
[UIView animateWithDuration:0.5 animations:^{
[self hidePlayerControl];
}];
}
else{
lastControlTime = CFAbsoluteTimeGetCurrent();
[UIView animateWithDuration:0.5 animations:^{
[self showPlayerControl];
}];
}
}else if(recognizer.view == playerSlider){
isSilderTouched = YES;
lastControlTime = CFAbsoluteTimeGetCurrent();
CGPoint translation = [recognizer locationInView:recognizer.view]; // obtain touch location
float rate = translation.x / (landScapeScreenWidth*0.8f); // calculate corresponded playback Rate
playerSlider.value = rate; // update player slider value
self.moviePlayer.currentPlaybackTime = self.moviePlayer.duration * rate; // seek movie
currentTimeLabel.text = [self secondsToMMSS:self.moviePlayer.currentPlaybackTime]; //update current play time
NSLog(@"%f",translation.x);
NSLog(@"click outside");
}
}
For full version source code, please click here