i created a MPMoviePlayerViewController in my UIView (not in my UIVIewController!) like this:
self.playButton = [[UIButton alloc] initWithFrame:CGRectMake(100, 70, 125, 100)];
[self.playButton setBackgroundImage:[UIImage imageNamed:#"video_play.png"] forState:UIControlStateNormal];
[self.playButton addTarget:self action:#selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
self.playerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:videoURL];
self.playerViewController.moviePlayer.fullscreen = NO;
self.playerViewController.view.frame = CGRectMake(0, 0, 320, 200);
[self.playerViewController.moviePlayer prepareToPlay];
self.playerViewController.moviePlayer.shouldAutoplay = NO;
self.playerViewController.view.backgroundColor = [UIColor yellowColor];
[self addSubview:self.playerViewController.view];
[self.playerViewController.view addSubview:self.playButton];
}
- (void)buttonPressed:(id)sender{
(NSLog(#"Click"));
[self.playerViewController.moviePlayer setFullscreen:YES animated:YES];
[self.playerViewController.moviePlayer play];
}
As you can see i added a Button on the videoView, beacause this part should only be a Preview and when the user clicks on the Button the MPMoviePlayerViewController should animate to fullscreen and start playing, and when the Video is finished it should go back to the Preview View. Everything works so far, but i have two Problems:
First Problem:
Everytime i open the View my StatusBar becomes hidden and it looks like this:
So i set in my viewWillAppear and viewDidAppear of my UIViewController:
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
This works, but now the statusbar gets hidden and immediately appears again, that looks ugly, any chance to solve this Problem?
Second Problem:
When i click on the Custom Button the Video gets fullscreen and everything works correct! But when i press the DONE Button of the Video everything goes back to the Preview Screen and it looks like this: The StatusBar is hidden, the navigationbar is also broken and there is a lot of black Space above the Video, whats the Problem here?
Ok i found a solution for this Problem, its a little bit hacky but i found no other solution. In my ViewController i do:
- (void)viewDidLoad {
[super viewDidLoad];
float delay = 0.1;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[UIApplication sharedApplication].statusBarHidden = NO;
});
and for the case User taps back Button i do:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[UIApplication sharedApplication].statusBarHidden = NO;
}
Related
I know possibly this is duplicate question but the question which is already exist didn't have an solution so , I'm asking again to possibly start bounty question .
Here is my code which is working below iOS 11 :
AVPlayer *player = [AVPlayer playerWithURL:videoURL];
// create a player view controller
avcontroller = [[AVPlayerViewController alloc]init];
avcontroller.player = player;
[player play];
NSNotificationCenter *noteCenter = [NSNotificationCenter defaultCenter];
[noteCenter addObserverForName:AVPlayerItemDidPlayToEndTimeNotification
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
NSLog(#"Video end");
self.avcontroller.player = nil;
[self.avcontroller.view removeFromSuperview];
[self.view addSubview:delegate.tabViewControllerObj.tabBarController.view];
}];
_skip =[UIButton buttonWithType:UIButtonTypeCustom];
[_skip addTarget:self action:#selector(btnSkipTapped)
forControlEvents:UIControlEventTouchUpInside];
[_skip setTitle:#"Skip" forState:UIControlStateNormal];
_skip.layer.borderWidth = 2.0f;
_skip.layer.cornerRadius = 12;
_skip.clipsToBounds = YES;
_skip.layer.borderColor = [UIColor whiteColor].CGColor;
// show the view controller
[self addChildViewController:avcontroller];
[avcontroller.view addSubview:_skip];
[avcontroller.view bringSubviewToFront:_skip];
[self.view addSubview:avcontroller.view];
avcontroller.view.frame = self.view.frame;
}
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
_skip.frame = CGRectMake((self.view.frame.size.width-140),(self.view.frame.size.height-150),100.0,35.0);
}
And here is button tapped function:
- (IBAction)btnSkipTapped{
NSLog(#"Skip button clicked");
self.avcontroller.player = nil;
[self.avcontroller.view removeFromSuperview];
[self.view addSubview:delegate.tabViewControllerObj.tabBarController.view];
}
This code will display button perfectly but upon button tap , it didn't call btnSkipTapped function.
Any help would be appreciated !
#DeepShah you have added skip button in avcontroller.view so its display proper but you can't click on it because AVPlayerViewControllerContentView covers that skip button.
see below image :
so you have to add skip button in self.view and its works.
[self.view addSubview:_skip];
[self.view bringSubviewToFront:_skip];
Every time I add MPVolumeView as a subview to my UIViewController’s view, there is a quick animation (the MPVolumeView expands from left to right) which looks really weird. I’m looking for a way to get rid of this animation, has anyone faced this issue?
I almost accepted that this is a MPVolumeView bug but then I noticed that Apple is definitely using a MPVolumeView in their native music app, no weird animations there...
So there must be something I'm doing wrong.
UPDATE:
The code is pretty straightforward but it was requested in the comments, so here it is:
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(10.f, 0.f, CGRectGetWidth(self.view.frame) - 20.f, 30.f)];
[[UISlider appearanceWhenContainedIn:[MPVolumeView class], nil] setMinimumValueImage:[UIImage imageNamed:#"icon-volumeMin"]];
[[UISlider appearanceWhenContainedIn:[MPVolumeView class], nil] setMaximumValueImage:[UIImage imageNamed:#"icon-volumeMax"]];
volumeView.center = CGPointMake(0.5f * CGRectGetWidth(self.view.frame), 0.5f * CGRectGetHeight(self.view.frame));
volumeView.showsRouteButton = NO;
[self.view addSubview:volumeView];
I made a very simple project on github to demostrate the problem, but you have to run it on a device, since MPVolumeView does not show up on simulator. Or just take a look at this gif:
:
One possible way to remove this behavior is to subclass MPVolumeView and perform some additional work after [super layoutSubviews].
- (void)layoutSubviews
{
[super layoutSubviews];
[self xy_recursiveRemoveAnimationsOnView:self];
}
- (void)xy_recursiveRemoveAnimationsOnView:(UIView *)view
{
[view.layer removeAllAnimations];
for (UIView *subview in view.subviews) {
[self xy_recursiveRemoveAnimationsOnView:subview];
}
}
This removes all inserted animations. So be sure that is what you want, since this is quite the overkill. One could also just remove the position and bounds animations (see removeAnimationForKey:).
i fixed your demo-code
#implementation F17YViewController {
MPVolumeView *volumeView;
}
- (void)viewDidLoad {
[super viewDidLoad];
volumeView = [[MPVolumeView alloc] init];
volumeView.showsRouteButton = NO;
volumeView.hidden = true;
[[UISlider appearanceWhenContainedIn:[MPVolumeView class], nil] setMinimumValueImage:[UIImage imageNamed:#"icon-volumeMin"]];
[[UISlider appearanceWhenContainedIn:[MPVolumeView class], nil] setMaximumValueImage:[UIImage imageNamed:#"icon-volumeMax"]];
[self.view addSubview:volumeView];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
volumeView.frame = CGRectMake(10.f, 0.f, CGRectGetWidth(self.view.frame) - 20.f, 30.f);
volumeView.center = CGPointMake(0.5f * CGRectGetWidth(self.view.frame), 0.5f * CGRectGetHeight(self.view.frame));
}
- (IBAction)showVolumeView:(id)sender {
volumeView.hidden = false;
}
You should do layout calls in viewWillLayoutSubviews.
Instead of creating a new MPVolumeView with each button press you should create one at viewDidLoad and hide it and then unhide when the button gets pressed.
I need to add a custom button to the AVPlayerViewController that will appear in both fullscreen and non-fullscreen for an app running iOS 8.
Adding a button to the AVPlayerViewController.view or the containing view will work for non-fullscreen but when the player switches to fullscreen the button is no longer visible. I have found that if I add a button to the AVPlayerViewController.ContentOverlayView then it appears in fullscreen and non-fullscreen, but then it doesn't appear that the ContentOverlayView responds to any touches so the button cannot be clicked. Does anyone know of a different place to add the button or a way to make the ContentOverlayView respond to touches?
Example Code
AVPlayerViewController *playerView = [[AVPlayerViewController alloc] init];
playerView.player = [AVPlayer playerWithURL:movieURL];
CGRect viewInsetRect = CGRectInset ([self.view bounds],
kMovieViewOffsetX,
kMovieViewOffsetY );
/* Inset the movie frame in the parent view frame. */
[[playerView view] setFrame:viewInsetRect];
[self.view addSubview: [playerView view]];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.backgroundColor = [UIColor yellowColor];
btn.frame = CGRectMake(50, 50, 200, 75);
[btn addTarget:self action:#selector(didSelectButton:) forControlEvents:UIControlEventTouchUpInside];
[btn setUserInteractionEnabled:YES];
[btn setEnabled:YES];
[playerView.contentOverlayView addSubview:btn];
I managed to get this working by adding the following to my AVPlayerViewController in IB:
An overlay view with a button inside it
Add constraints to center the button in the overlay view
Created an IBOutlet to the view (I called it 'overlay')
Created an action from the button to AVPlayerViewController that prints something so that we can see that tapping the button is working
Dragged the overlay view out of the view hierarchy and onto the top bar of the view controller (appears as a view icon in top bar of the view controller along with the exit icon etc)
and then in the code for the AVPlayerViewController:
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.overlay)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.overlay.frame = self.view.bounds
}
#IBAction func playBtnTapped(sender: AnyObject) {
println("PlayBtnTapped")
}
The button is now centered in fullscreen/normal viewing and the button works
I had the same predicament just now.
Instead of:
[playerView.contentOverlayView addSubview:btn];
use (after you add the playerView)
[self.view addSubview:btn];
This will add the button in the minimised player.
Now for the fullscreen I didn't found any other reliable method of checking if the player went fullscreen or back, so here is a a solution:
self.windowChecker = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(checkIfFullscreen) userInfo:nil repeats:YES];
and this:
-(void)checkIfFullscreen{
NSLog(#"videoBounds\n %f %f ", self.avVideoPlayer.contentOverlayView.frame.size.width,self.avVideoPlayer.contentOverlayView.frame.size.height);
if ([self playerIsFullscreen]) { // check the frame on this
for(UIWindow* tempWindow in [[UIApplication sharedApplication]windows]){
for(UIView* tempView in [tempWindow subviews]){
if ([[tempView description] rangeOfString:#"UIInputSetContainerView"].location != NSNotFound){
UIButton *testB = [[UIButton alloc] initWithFrame: CGRectMake(20, 20, 400, 400)];
testB.backgroundColor = [UIColor redColor];
[testB addTarget:self action:#selector(buttonTouch) forControlEvents:UIControlEventTouchDown];
[tempView addSubview:testB];
break;
}
}
}
}
}
I know this is a not a nice way to do it, but it is the only way I managed to add some custom UI that also receives touch events on the player.
Cheers!
I am using MPMoviePlayerController to play a video inside my iPad application. I am using below code snippet to add the movie player to view:
self.player =[[MPMoviePlayerController alloc] initWithContentURL: urlVideo];
[self.player prepareToPlay];
[self.player setMovieSourceType:MPMovieSourceTypeStreaming];
[self.player.view setBounds:CGRectMake(0, 0, 512, 374)];
if (UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))
{
NSLog(#"landscape..");
[self.player.view setCenter:CGPointMake(512, 374)];
}
else{
NSLog(#"portrait.");
[self.player.view setCenter:CGPointMake(384, 502)];
}
self.player.controlStyle=MPMovieControlStyleEmbedded;
[self.player setScalingMode:MPMovieScalingModeAspectFit];
self.player.shouldAutoplay=YES;
[self.viewController.view addSubview: self.player.view];
self.btnCloseNormalMode= [UIButton buttonWithType:UIButtonTypeCustom];
[self.btnCloseNormalMode setImage:[UIImage imageNamed:#"close_button_icon.png"] forState:UIControlStateNormal];
[self.btnCloseNormalMode setFrame:CGRectMake(470, 5, 32, 32)];
[self.btnCloseNormalMode addTarget:self action:#selector(onSmallCloseBtnTap) forControlEvents:UIControlEventTouchUpInside];
[self.player.view addSubview:self.btnCloseNormalMode];
But as understandable from the above code, its adding on the view abruptly. Suddenly one black view appears on the view which is not user friendly. We want to add the movie player view with some animation to make it smooth. Can I make the movie player view to come with a animation like how modal appears or any suitable UIView animation. But I have no idea regarding animation. Could someone please help me on this !!! Thanks.
Since iOS 7 rolled out, I can't show or hide status bar with animation just like in iOS 6.
For now I use NSTimer to control it when to hide.
here is my code:
- (void)hideStatusBar{
_isStatusBarHidden=YES;
[self performSelector:#selector(setNeedsStatusBarAppearanceUpdate)];
}
- (void)showStatusBar{
_isStatusBarHidden=NO;
[self performSelector:#selector(setNeedsStatusBarAppearanceUpdate)];
}
//===================
_controlVisibilityTimer = [[NSTimer scheduledTimerWithTimeInterval:4 target:self selector:#selector(hideStatusBar:) userInfo:nil repeats:NO] retain];
But unfortunately the way of status bar hiding seems a little bit rough, not fading away. Is someone out there has a solution to this ?
Update
I solved the hiding issue, using #hahaha solution. I just need a view to be the background of the status bar, here is my code.
AppDelegate* appDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
self.StatusBarOrange = [[UIView alloc] initWithFrame:CGRectMake(0, 0, appDelegate.window.frame.size.width, 20)];
[self.StatusBarOrange setBackgroundColor:[UIColor orangeColor]];
[appDelegate.window.rootViewController.view addSubview:self.StatusBarOrange];
and now everything works perfectly!
You need to call
[UIViewController setNeedsStatusBarAppearanceUpdate];
from within an animation block as in the following example:
#implementation SomeViewController {
BOOL _statusBarHidden;
}
- (BOOL)prefersStatusBarHidden {
return _statusBarHidden;
}
- (void)showStatusBar:(BOOL)show {
[UIView animateWithDuration:0.3 animations:^{
_statusBarHidden = !show;
[self setNeedsStatusBarAppearanceUpdate];
}];
}
#end