如何使 MPMoviePlayerViewController 以横向模式启动但仍允许更改方向

发布于 2024-11-25 06:25:34 字数 2077 浏览 0 评论 0原文

这里有很多与将电影播放锁定为横向模式或使用 MPMoviePlayerViewController 或 MPMoviePlayerController 支持电影横向播放相关的问题。我已经具有横向/纵向功能,并且我不想将播放锁定到任一模式。

我所拥有的是使用 MPMoviePlayerViewController 的代码,如文档所示,本质上是:

    MPMoviePlayerViewController* movieViewController = 
        [[MPMoviePlayerViewController alloc] initWithContentURL:url];
    [parentViewController presentMoviePlayerViewControllerAnimated:movieViewController];

我的应用程序大部分锁定为纵向模式,但此代码在其自己的视图中以模态方式呈现电影控制器,并支持纵向和横向方向。所有这些都非常好。

但这是我的问题。我将展示的 99% 的视频都是横向视频,上面的代码以纵向模式启动电影播放,因为用户(可能)以纵向模式握住设备。

我想要的是原生 YouTube 应用的行为;当您呈现电影控制器时,它首先以横向模式呈现,这将提示用户更改设备的方向。如果他们稍后想要将其旋转回纵向,他们可以这样做。当电影完成(或关闭)时,电影视图控制器将关闭,并且设备应处于纵向模式。

似乎不可能正确隐藏状态栏(无论启动电影之前“hideStatusBar”的状态如何,它都与全屏控件相关),因此似乎将状态栏置于正确的位置也需要成为这一部分。

编辑添加状态栏方向的调试注释: 如果我在启动影片之前调用 setStatusBarOrientation:UIInterfaceOrientationLandscapeRight ,状态栏位于正确的位置,但系统不再以相同的方式调用 shouldAutorotateToInterfaceOrientation

如果我不调用 setStatusBarOrientation,在电影出现之前,我会收到以下调用序列:

shouldAutorotateToInterfaceOrientation(Portrait)
shouldAutorotateToInterfaceOrientation(Portrait)
shouldAutorotateToInterfaceOrientation(Portrait)
shouldAutorotateToInterfaceOrientation(Right)
shouldAutorotateToInterfaceOrientation(Portrait)

我仅向右侧回答 YES,电影在 LandscapeRight 中启动,但状态栏位于错误的地方。设备方向的后续更改将准确生成您期望的 shouldAutorotateToInterfaceOrientation 调用(例如,如果我旋转到纵向,它会询问我是否可以旋转到纵向)。

如果我确实调用 setStatusBarOrientation:UIInterfaceOrientationLandscapeRight,我会得到以下序列:

shouldAutorotateToInterfaceOrientation(Right)
shouldAutorotateToInterfaceOrientation(Right)

我对这两个问题都回答“是”。状态栏位于正确的位置,但我不再接到 shouldAutorotateToInterfaceOrientation 的电话询问有关纵向模式的问题。因此,如果我将设备旋转到右侧,然后返回到纵向,然后返回到右侧,我会看到它调用 shouldAutorotateToInterfaceOrientation(Right) 两次。更奇怪的是,如果我将其一直旋转到左侧方向,我确实会得到 shouldAutorotateToInterfaceOrientation(Left) 从那时起一切正常。这是最烦人的。

我想这一定是iOS端的一个bug,这就是为什么YouTube应用程序不使用动画UI旋转效果的原因。相反,它会隐藏全屏控件(包括状态栏),在后台隐形旋转,然后重新显示控件。

There are a multitude of questions here relating to locking movie playback into landscape mode, or supporting landscape playback of movies using MPMoviePlayerViewController or MPMoviePlayerController. I already have landscape/portrait functionality, and I don't want to lock the playback to either mode.

What I have is code which uses MPMoviePlayerViewController as the docs suggest, essentially:

    MPMoviePlayerViewController* movieViewController = 
        [[MPMoviePlayerViewController alloc] initWithContentURL:url];
    [parentViewController presentMoviePlayerViewControllerAnimated:movieViewController];

My app is mostly locked to portrait mode, but this code presents the movie controller modally in its own view, and supports both portrait and landscape orientations. All of which is very nice.

Here is my problem though. 99% of the videos I will be presenting are landscape videos, and the above code starts the movie playback in portrait mode, because the user is (likely) holding the device in portrait mode.

What I want is the behaviour of the native YouTube app; that when you present the movie controller, it first presents in landscape mode, which will prompt the user to change their device's orientation. If they later on want to rotate it back to portrait they are allowed to. When the movie is done (or dismissed), the movie view controller will be dismissed, and the device should be in portrait mode.

It seems impossible to hide the status bar properly (it's tied to the full screen controls regardless of the state of 'hideStatusBar' before launching the movie), so it seems that getting the status bar to be in the right place also needs to be a part of this.

Edited to add debugging notes for status bar orientation:
If I call setStatusBarOrientation:UIInterfaceOrientationLandscapeRight before launching the movie, the status bar is in the right place, but the system no longer calls shouldAutorotateToInterfaceOrientation in the same way.

If I don't call setStatusBarOrientation, prior to the movie appearing I get the following sequence of calls:

shouldAutorotateToInterfaceOrientation(Portrait)
shouldAutorotateToInterfaceOrientation(Portrait)
shouldAutorotateToInterfaceOrientation(Portrait)
shouldAutorotateToInterfaceOrientation(Right)
shouldAutorotateToInterfaceOrientation(Portrait)

I answer YES only to the Right, and the movie launches in LandscapeRight, but with the status bar in the wrong place. Subsequent changes of device orientation generate exactly the shouldAutorotateToInterfaceOrientation calls you'd expect (e.g. if I rotate to Portrait, it asks me if it's okay to rotate to Portrait).

If I do call setStatusBarOrientation:UIInterfaceOrientationLandscapeRight, I get the following sequence:

shouldAutorotateToInterfaceOrientation(Right)
shouldAutorotateToInterfaceOrientation(Right)

Both of which I answer YES to. The status bar is in the right place, but I no longer get an calls to shouldAutorotateToInterfaceOrientation asking about Portrait mode. So if I rotate the device to Right, then back to Portrait, then back to Right, I see it call shouldAutorotateToInterfaceOrientation(Right) twice. Even stranger, if I rotate it all the way around to the Left orientation, I do get shouldAutorotateToInterfaceOrientation(Left) and from then on everything works fine. Which is most annoying.

I think it must be a bug on the iOS side, and that's why the YouTube app doesn't use the animated UI rotation effects. Instead it hides the full screen controls, including the status bar, rotates invisibly in the background, and then re-shows the controls.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

病女 2024-12-02 06:25:34

我建议设置一个计时器;首先只允许在 shouldAutorotateToInterfaceOrientation: 中横向(这将强制旋转为横向),然后在(比如说)5 秒后,允许所有方向。

首先,您需要子类化 MPMoviePlayerViewController 或在其自己的视图中创建 MPMoviePlayerController。额外的代码看起来像这样:

// On load, init or similar method
BOOL showLandscapeOnly = YES;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@(allowAllOrientations) userInfo:nil repeats:NO];

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
  if (showLandscapeOnly == YES)
    return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
            interfaceOrientation == UIInterfaceOrientationLandscapeRight);
  else
    return YES;
}

- (void)allowAllOrientations {
  showLandscapeOnly = NO;
}

我认为这将准确地提供您所追求的;在显示模态视频控制器时,它会将方向翻转为横向,因为这是唯一受支持的方向。但如果用户将其恢复为纵向,它就会做出很好的响应。

您还可以尝试其他时间间隔;也许2秒会更好?建议您看看测试用户主题做了什么。他们可能很快就会旋转设备。

希望有帮助!

I would suggest setting off a timer; allow only landscape in shouldAutorotateToInterfaceOrientation: at first (which will enforce a rotation to landscape), and then after (say) 5 seconds, allow all orientations.

Firstly you need to either subclass MPMoviePlayerViewController or create an MPMoviePlayerController in its own view. The extra code would look something like this:

// On load, init or similar method
BOOL showLandscapeOnly = YES;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@(allowAllOrientations) userInfo:nil repeats:NO];

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
  if (showLandscapeOnly == YES)
    return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
            interfaceOrientation == UIInterfaceOrientationLandscapeRight);
  else
    return YES;
}

- (void)allowAllOrientations {
  showLandscapeOnly = NO;
}

I reckon this would deliver exactly what you're after; on showing the modal video controller, it would flip the orientation to landscape as this is the only supported orientation. But if the user turned it back to portrait, it would then respond fine.

You could also try experimenting with other time intervals; perhaps 2 seconds would be better? Suggest you see what test user subjects do. They probably rotate the device pretty quickly.

Hope that helps!

漫雪独思 2024-12-02 06:25:34

您必须旋转影片的帧,然后告诉应用程序委托在听到旋转消息时不要自行旋转。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return NO;
}

You're going to have to rotate the movie's frame, and then tell the app delegate to not rotate itself when it hears the rotation messages.

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return NO;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文