iPhone - 全屏和状态栏的典型问题

发布于 10-24 08:10 字数 1061 浏览 7 评论 0原文

在我的应用程序中,默认情况下状态栏是可见的。我的应用程序支持横向和纵向。 当我想播放视频时,我隐藏状态栏,以便我的视频全屏显示。当视频完成时,我将恢复状态栏。

我使用以下代码来显示视频:(

UIWindow* window = [[UIApplication sharedApplication] keyWindow];
[window addSubview:playerView]; 

我不能在代码中使用视图控制器。这是一个限制)

现在的问题是: 我的应用程序现在处于横向状态,单击按钮,我将隐藏状态栏并开始播放视频。播放视频时,我将手机方向更改为纵向,然后允许视频完成。视频完成后,设备仍处于纵向模式,播放器视图将被删除,状态栏将再次显示。现在我注意到我的纵向视图向上移动了 20 像素,超过了状态栏显示的位置。但是当我第一次启动该应用程序时,状态栏首先显示,在其下方显示我的视图。

我该如何处理这种情况?

简而言之,在视图控制器中使用以下代码。

- (void)viewDidLoad {
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    [self performSelector:@selector(showStatusAgain) withObject:nil afterDelay:6.0];
    [super viewDidLoad];
}

-(void)showStatusAgain
{
    [[UIApplication sharedApplication] setStatusBarHidden:NO];
}


// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

当您使用上面的代码运行应用程序时,它将以纵向启动。现在将其旋转为横向。你可以注意到这个问题。

In my application by default status bar is visible. And my app supports landscape as well as portrait orientations.
When I want to play the video, i'm hiding the status bar, so that my video will be shown full screen. And when video completes, i'm bringing the status bar back.

I'm using following code to show the video:

UIWindow* window = [[UIApplication sharedApplication] keyWindow];
[window addSubview:playerView]; 

(I can't use view controllers in my code. That's a restriction)

Now the problem:
My app is in landscape now, on click of a button, i'll hide the status bar and starts playing video. When video is playing, i change the orientation of the phone to portrait and I allowed video to complete. When video completed, the device is still in portrait mode, player view is removed and status bar is shown again. Now I noticed that my portrait view is moved 20 pixels up and over that the status bar is showing. But when I started the app for firs time, status bar is shown first and below it, my view is shown.

How should I handle this situation?

In simple use the following code in a view controller.

- (void)viewDidLoad {
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    [self performSelector:@selector(showStatusAgain) withObject:nil afterDelay:6.0];
    [super viewDidLoad];
}

-(void)showStatusAgain
{
    [[UIApplication sharedApplication] setStatusBarHidden:NO];
}


// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

when u run the app with above code, it will start in portrait. now rotate it to landscape. and you can notice the issue.

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

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

发布评论

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

评论(2

迷荒2024-10-31 08:10:20

我遇到了类似的问题,我通过 UINavigationController 上的类别解决了这个问题。

UINavigationController+LayoutCorrecting.h:

@interface UINavigationController (LayoutCorrecting)

- (void)recalculateNavigationBarFrameRelativeToStatusBar;

@end

UINavigationController+LayoutCorrecting.m:

#import "UINavigationBar+LayoutCorrecting.h"

#import "UIViewAdditions.h"

@implementation UINavigationController (LayoutCorrecting)

- (void)recalculateNavigationBarFrameRelativeToStatusBar {
    CGRect sbf = [[UIApplication sharedApplication] statusBarFrame];

    if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
        self.navigationBar.top = sbf.size.width;

    else
        self.navigationBar.top = sbf.size.height;
}

@end

如果你通过在 UIViewController 上声明它来稍微调整这个类别,并确保它调整controller.view.frame而不是navigationBar.top,我想你会很高兴去。只需确保在电影播放完毕并且已经显示状态栏后调用视图控制器上的类别方法即可。

为了避免任何混乱,可能值得一提的是,您需要在横向模式下使用状态栏的宽度,因为 UIWindow 的坐标系统总是像纵向一样工作,无论您如何握住设备。这与由 UIViewController 管理的子视图(UIView 实例)形成对比,子视图受益于自动坐标转换。

PS:由于您必须在窗口上下文中调整视图的框架,因此此功能也可能有所帮助。

CGRect CGRectOffsetRectForOrientation(CGRect rect, CGFloat dx, CGFloat dy, UIInterfaceOrientation orientation) {
    CGRect newRect = rect;

    switch (orientation) {
        case UIInterfaceOrientationPortrait:
            newRect.origin.x += dx;
            newRect.origin.y += dy;
            break;

        case UIInterfaceOrientationPortraitUpsideDown:
            newRect.origin.x -= dx;
            newRect.origin.y -= dy;
            break;

        case UIInterfaceOrientationLandscapeLeft:
            newRect.origin.y -= dx;
            newRect.origin.x += dy;
            break;

        case UIInterfaceOrientationLandscapeRight:
            newRect.origin.y += dx;
            newRect.origin.x -= dy;
            break;

        default:
            break;
    }

    return newRect;
}

I encountered a similar problem, which I solved with a category on UINavigationController.

UINavigationController+LayoutCorrecting.h:

@interface UINavigationController (LayoutCorrecting)

- (void)recalculateNavigationBarFrameRelativeToStatusBar;

@end

UINavigationController+LayoutCorrecting.m:

#import "UINavigationBar+LayoutCorrecting.h"

#import "UIViewAdditions.h"

@implementation UINavigationController (LayoutCorrecting)

- (void)recalculateNavigationBarFrameRelativeToStatusBar {
    CGRect sbf = [[UIApplication sharedApplication] statusBarFrame];

    if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
        self.navigationBar.top = sbf.size.width;

    else
        self.navigationBar.top = sbf.size.height;
}

@end

If you tweak this category a bit by declaring it on UIViewController, and making sure it adjusts controller.view.frame rather than navigationBar.top, I think you'll be good to go. Just make sure to call the category method on your view controller after your movie finishes playing and you've already shown the status bar.

And just for the sake of staving off any confusion, it's probably worth mentioning you need to use the width of the status bar in landscape mode because UIWindow's coordinate system always works as though it's in portrait, despite how you hold the device. This is in contrast to subviews (UIView instances) that get managed by a UIViewController, which benefit from automatic coordinate transformations.

P.S.: Since you're going to have to tweak your view's frame in a window context, this function may also help.

CGRect CGRectOffsetRectForOrientation(CGRect rect, CGFloat dx, CGFloat dy, UIInterfaceOrientation orientation) {
    CGRect newRect = rect;

    switch (orientation) {
        case UIInterfaceOrientationPortrait:
            newRect.origin.x += dx;
            newRect.origin.y += dy;
            break;

        case UIInterfaceOrientationPortraitUpsideDown:
            newRect.origin.x -= dx;
            newRect.origin.y -= dy;
            break;

        case UIInterfaceOrientationLandscapeLeft:
            newRect.origin.y -= dx;
            newRect.origin.x += dy;
            break;

        case UIInterfaceOrientationLandscapeRight:
            newRect.origin.y += dx;
            newRect.origin.x -= dy;
            break;

        default:
            break;
    }

    return newRect;
}
尝蛊2024-10-31 08:10:20

尝试在显示时更新状态栏样式:

[[UIApplication sharedApplication] setStatusBarHidden:NO];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefualt];

Try to update the status bar style when you show it:

[[UIApplication sharedApplication] setStatusBarHidden:NO];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefualt];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文