Подтвердить что ты не робот

Полноэкранное воспроизведение MPMoviewPlayerController с базовым UIViewController только с портретным режимом (вращение запрещено)

Алло,

У меня есть простое приложение, которое содержит UITabBarController с двумя UIViewControllers. Оба UIViewControllers являются только портретами (разрешение вращения не разрешено). Один UIViewController UIView имеет представление MPMoviePlayerController, чтобы разрешить воспроизведение видео в этом представлении с возможностью сделать его в полноэкранном режиме с помощью элементов управления (MPMovieControlStyleEmbedded). Код прост и выглядит как...

__moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:@"MOVIE_URL"]];
__moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
__moviePlayer.view.frame = CGRectMake( 10, 10, 300, 200 );
__moviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
__moviePlayer.shouldAutoplay = NO;
[__moviePlayer prepareToPlay];  
[self.view addSubview:__moviePlayer.view];

... это отлично работает, если пользователь не переключится на полноэкранное воспроизведение, где я хочу разрешить поворот, чтобы можно было воспроизводить пейзаж. Вращение не работает, потому что UITabBarController запрещает его (и оба UIViewControllers тоже).

Итак, я попробовал два подхода, но ни один из них не работает должным образом.

1) Подклассифицированный UITabBarController

Я добавил свойство BOOL __allowRotation, и если он установлен в YES, я возвращаю YES в UITabBarController shouldAutorotateToInterfaceOrientation.

Я слушаю MPMoviePlayerDidEnterFullscreenNotification и MPMoviePlayerWillExitFullscreenNotification уведомления, чтобы установить это свойство в YES и NO.

Это работает, но проблема в том, что когда пользователь заканчивает воспроизведение видео в ландшафтном режиме, основной вид не поворачивается назад к портрету. Единственный способ повернуть назад к портрету - использовать частный API, который нет.

2) Просмотр/преобразование слоев

Я также попытался прослушать уведомления MPMoviePlayerDidEnterFullscreenNotification и MPMoviePlayerWillExitFullscreenNotification.

Когда я получаю MPMoviePlayerDidEnterFullscreenNotification, я начинаю уведомления о ориентации UIDevice, чтобы получить ориентацию устройства. Я пытаюсь преобразовать слой представления MPMoviePlayerController, основанный на текущей ориентации устройства, но он невосприимчив, потому что он ничего не делает. Я могу назначить все для преобразования свойства, но ничего не делает.

Делает ничего не совсем правильно. Когда я применяю преобразование во время вращения, я могу увидеть эффект этого преобразования, когда я переключаюсь с полноэкранного воспроизведения на встроенное видео.

3) Разделите UIWindow

Я еще не тестировал это, но где-то я нашел, что MPMoviePlayerController создает отдельный UIWindow для полноэкранного воспроизведения, который должен быть доступен через окна [[UIApplication sharedApplication]]. Это объясняет, почему преобразование не применяется во время полноэкранного воспроизведения.

Но я очень не люблю это решение, потому что UIWindow не может быть идентифицирован, и я не хочу использовать магические константы, такие как objectAtIndex: 1 или применить преобразование ко всем UIWindows, кроме основного, и т.д.

Кроме того, что базовая реализация может быть изменена, и она перестанет работать.

Вопрос

Итак, вопрос в том, как разрешить полноэкранному воспроизведению MPMoviePlayerController только вращение, когда базовый UIView (то есть UIView UIViewController) запрещает поворот и позволяет только портрет?

4b9b3361

Ответ 1

Вы можете попытаться представить новый UIViewController (с mustAutorotate YES) по умолчанию и добавить __moviePlayer.view в этот контроллер, когда он отправит MPMoviePlayerWillEnterFullscreenNotification. Сделайте обратное, когда moviePlayer выйдет из полноэкранного режима.

Ответ 2

У меня очень похожая ситуация. Мое приложение - только для портрета. Но мне нужно показать полноэкранные видеоролики в любой ориентации, а затем вернуться к портретной ориентации после выхода из полноэкранного режима.

Сплит-метод не работает для меня, потому что я хотел бы позволить пользователю смотреть видео в полноэкранном режиме и встроенном, а также переключаться между режимами, не теряя позицию воспроизведения, и без каких-либо пауз.

Я нашел это обходное решение:

Сначала у меня есть корневой подкласс UINavigationController, который получает все сообщения относительно вращения.

Я запрещаю вращение в этом контроллере с помощью:

- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)toInterfaceOrientation {
    return (UIInterfaceOrientationPortrait == toInterfaceOrientation);
}

Я переопределяю

- (id) initWithRootViewController:(UIViewController *)rootViewController; method. 

Добавление поддержки модификаций ориентации устройства:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(receivedRotate:) name: UIDeviceOrientationDidChangeNotification object: nil];

Теперь у меня есть обработчик, полученныйRotate: - который ловит все вращения устройства, несмотря на то, что он не поворачивается автоматически к любым ориентациям, кроме портрета:

- (void) receivedRotate:(NSNotification*) notify {
    if(isVideoFullscreen) {
        UIDeviceOrientation toInterfaceOrientation = [[UIDevice currentDevice] orientation];
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.4];
        [UIView setAnimationCurve:2];

        if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft){
            self.view.transform = CGAffineTransformMakeRotation(-M_PI_2);
            [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
            self.view.bounds = CGRectMake(0, 0, 1024, 768);
        } else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
            self.view.transform = CGAffineTransformMakeRotation(M_PI_2);
            [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; 
            self.view.bounds = CGRectMake(0, 0, 1024, 768);            
        } else if(toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
            self.view.transform = CGAffineTransformMakeRotation(M_PI);
            [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortraitUpsideDown];
            self.view.bounds = CGRectMake(0, 0, 768, 1024);
        } else if(toInterfaceOrientation == UIInterfaceOrientationPortrait) {
            self.view.transform = CGAffineTransformMakeRotation(0);
            [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
            self.view.bounds = CGRectMake(0, 0, 768, 1024);
        }

        [UIView commitAnimations];
    }

}

Я просто проверяю вращения устройства и соответственно поворачиваю свое представление.

Затем - как знает корневой контроллер, когда видео полноэкранное? Просто добавьте два других обработчика сообщений в init:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterFullscreen:) name:MPMoviePlayerWillEnterFullscreenNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willExitFullscreen:) name:MPMoviePlayerWillExitFullscreenNotification object:nil];

И сами обработчики:

- (void) willEnterFullscreen: (NSNotification *) notify {
    isVideoFullscreen = YES;
}

- (void) willExitFullscreen: (NSNotification *) notify {
    self.view.transform = CGAffineTransformMakeRotation(0);
    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
    self.view.bounds = CGRectMake(0, 0, 768, 1024);    
    isVideoFullscreen = NO;
}

При выходе из полноэкранного режима - мы восстанавливаем портретную ориентацию. Итак, это работает для меня, надеюсь, что это поможет кому-то.

Ответ 3

Зарегистрируйтесь для MPMoviePlayerWillExitFullscreenNotification и MPMoviePlayerWillEnterFullscreenNotification в делегате приложения и обрабатывайте ориентацию с использованием переменной экземпляра.

-(void)moviePlayerFullScreen:(NSNotification *)notification
{
    if ([notification.name isEqualToString:@"MPMoviePlayerWillEnterFullscreenNotification"]) {

        self.supportedOrientation=UIInterfaceOrientationMaskAll;

    }
    else if ([notification.name isEqualToString:@"MPMoviePlayerWillExitFullscreenNotification"])
    {
        self.supportedOrientation=UIInterfaceOrientationMaskPortrait;

    }
 }
 - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window  {
    return self.supportedOrientation;
}

Ответ 4

MPMoviePlayerViewController имеет свою собственную функцию для видеороликов:

NSURL *videoURL = [NSURL fileURLWithPath:video.path];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];

//Calls for movie playback once video is finished
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(moviePlayBackDidFinish:)
                                             name:MPMoviePlayerPlaybackDidFinishNotification
                                           object:moviePlayer];
playerView = [[MPMoviePlayerViewController alloc]init];
[moviePlayer setControlStyle:MPMovieControlStyleFullscreen];
[playerView setView:moviePlayer.view];

[moviePlayer.view setFrame: self.view.bounds];  
[self presentMoviePlayerViewControllerAnimated:playerView];

[moviePlayer play];
NSLog(@"playing video view");

Ответ 5

Привет всем, у меня была такая же проблема, я ее разрешил -

Вот мой полный код....

Вам нужно сначала изменить appdelegate:

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if ([[[NowPlaying sharedManager] playerViewController] allowRotation])//Place your condition here
{
    return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}

Регистрация Уведомления для полноэкранного управления:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerWillEnterFullscreenNotification:)
                                             name:MPMoviePlayerWillEnterFullscreenNotification
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerWillExitFullscreenNotification:)
                                             name:MPMoviePlayerWillExitFullscreenNotification
                                           object:nil];

Затем добавьте строку кода в контроллер плеера:

- (void)moviePlayerWillEnterFullscreenNotification:(NSNotification *)notification
{
dispatch_async(dispatch_get_main_queue(), ^
               {
                   self.allowRotation = YES;
               });
}



- (void)moviePlayerWillExitFullscreenNotification:(NSNotification *)notification
{
self.allowRotation = NO;
[self.moviePlayerController setControlStyle:MPMovieControlStyleNone];

dispatch_async(dispatch_get_main_queue(), ^
               {

                   //Managing GUI in pause condition
                       if (self.currentContent.contentType == TypeVideo && self.moviePlayerController.playbackState == MPMoviePlaybackStatePaused)
                   {
                       [self.moviePlayerController pause];
                       if (self.playButton.selected)
                           self.playButton.selected = NO;
                   }
                   self.view.transform = CGAffineTransformMakeRotation(0);
                   [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
                   self.view.bounds = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
               });
}

Этот код проверен в iOS6 и iOS7. Благодаря

Пожалуйста, дайте мне знать, если есть какие-либо вопросы.....