ChatGPT解决这个技术问题 Extra ChatGPT

iOS 7 - 状态栏与视图重叠

我有一个位于 UINavigationcontroller 内的 ViewController,但导航栏是隐藏的。当我在 iOS 7 上运行应用程序时,状态栏显示在我的视图顶部。有没有办法避免这种情况?

我不想编写任何特定于操作系统的代码。

https://i.stack.imgur.com/IxX45.png

我尝试将 View controller-based status bar appearance 设置为 NO,但没有解决问题。

我已经发布了在 iOS 7 中显示 iOS 6 等状态栏的答案stackoverflow.com/questions/18294872/…
您还需要调整 y 原点和 delta 值以处理状态栏问题这可能会帮助您stackoverflow.com/q/18980925/1545180

P
Peter Mortensen

Xcode 5 有 iOS 6/7 Deltas 专门用于解决此问题。在情节提要中,我将视图向下移动了 20 像素,以便在 iOS 7 上看起来正确,为了使其与 iOS 6 兼容,我将 Delta y 更改为 -20。

https://i.stack.imgur.com/e4P7J.png

由于我的故事板没有使用自动布局,为了在 iOS 6 上正确调整视图的高度,我必须设置 Delta heightDelta Y


您的答案是正确的,但不适用于 4" 显示器。如果您也可以使其适用于 4" 显示器,请更新您的答案。提前致谢。
@AnkitMehta 我不必为 4" iphone 做任何特定的事情
为我工作。请注意,为了查看此增量,您必须取消选择情节提要的“身份和类型”下的“使用自动布局”。
我发现除了为 ∆Y 设置 -20 之外,我还必须为 ∆Height 设置 +20
当状态栏高度发生变化时会发生什么? F.ex.:当用户激活热点等......然后高度为40px......
N
Nathan H

如果您根本不想要任何状态栏,则需要使用以下数据更新您的 plist:为此,在 plist 中添加这 2 个设置:

<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

在 iOS 7 中,您应该在设计应用时考虑到覆盖透明状态栏。例如,请参阅新的 iOS 7 天气应用程序。


这实际上是唯一一个好的答案,因为它以本来应该完成的方式解决了问题的核心。所以:需要投票!
它可能适用于某些情况,但您要非常小心地隐藏状态栏。仅适用于完全全屏的视图,例如媒体播放器或图像查看器。
@eleven59,你的意思是苹果独裁者的意图。
绝对比更改视图控制器的偏移量(感觉很脏)更好。
隐藏状态栏不是一个好主意...我知道这是处理 iOS 7 的最简单方法,但需要时间...
B
Bhavin Ramani

这是 iOS 7 上 UIViewController 的默认行为。视图将是全屏的,这意味着状态栏将覆盖视图的顶部。

如果您在 UINavigationController 中有一个 UIViewController 并且导航栏是可见的,那么您可以在 viewDidLoad 中包含以下代码或为导航栏添加背景图片来解决问题。

self.edgesForExtendedLayout = UIRectEdgeNone;

如果您隐藏了导航栏,那么您必须通过移动 20 个点来调整所有 UIView 元素。我没有看到任何其他解决方案。使用自动布局会有所帮助。

如果您想向后兼容,这里是用于检测 iOS 版本的示例代码。

NSUInteger DeviceSystemMajorVersion() {
    static NSUInteger _deviceSystemMajorVersion = -1;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        NSString *systemVersion = [UIDevice currentDevice].systemVersion;
        _deviceSystemMajorVersion = [[systemVersion componentsSeparatedByString:@"."][0] intValue];
    });

   return _deviceSystemMajorVersion;
}

建议使用if ([self respondsToSelector:@selector(edgesForExtendedLayout)])而不是获取、解析和比较系统版本
T
Tim Kozak

我自己制作的唯一可行的解决方案。

这是我的 UIViewController 子类 https://github.com/comonitos/ios7_overlaping

1 UIViewController 的子类

从该类子类化您的 window.rootViewController。

3 瞧!

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        CGRect screen = [[UIScreen mainScreen] bounds];
        if (self.navigationController) {
            CGRect frame = self.navigationController.view.frame;
            frame.origin.y = 20;
            frame.size.height = screen.size.height - 20;
            self.navigationController.view.frame = frame;
        } else {
            if ([self respondsToSelector: @selector(containerView)]) {
                UIView *containerView = (UIView *)[self performSelector: @selector(containerView)];

                CGRect frame = containerView.frame;
                frame.origin.y = 20;
                frame.size.height = screen.size.height - 20;
                containerView.frame = frame;
            } else {
                CGRect frame = self.view.frame;
                frame.origin.y = 20;
                frame.size.height = screen.size.height - 20;
                self.view.frame = frame;
            }
        }
    }
}

添加这个让你的状态栏变白就在[self.window makeKeyAndVisible]之后; !!!

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}

但这并没有显示顶部的时间......最大的缺点...... :(
效果很好,但是对于第 4 步,您应该在视图控制器中使用 preferredStatusBarStyle,因为不推荐使用 setStatusBarStyle,它的默认操作是什么都不做。 stackoverflow.com/a/19014724/1192732
D
Darshit Shah
-(UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

-(void)viewWillLayoutSubviews{

 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
  {
    self.view.clipsToBounds = YES;
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    CGFloat screenHeight = 0.0;
    if(UIDeviceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))
        screenHeight = screenRect.size.height;
    else
        screenHeight = screenRect.size.width;
    CGRect screenFrame = CGRectMake(0, 20, self.view.frame.size.width,screenHeight-20);
    CGRect viewFrame1 = [self.view convertRect:self.view.frame toView:nil];
    if (!CGRectEqualToRect(screenFrame, viewFrame1))
    {
        self.view.frame = screenFrame;
        self.view.bounds = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    }
  }
}

在 plist 中添加键---查看基于控制器的状态栏外观:否


如果需要,更改窗口颜色
谢谢,它解决了我的重叠问题。但是一个问题仍然存在 - 查看基于控制器的状态栏外观:NO 是隐藏状态栏我猜。但是当我将其设置为 YES 时,它不会显示状态栏,当我将其设置为 NO 时,它会显示状态栏。所以请告诉我我的概念错了还是什么?
我认为是因为在 didFinishLaunchingWithOptions 'self.window.backgroundColor = [UIColor blueColor];' 中设置了默认的半透明颜色并在 plist 查看基于控制器的状态栏外观设置 YES
很好谢谢!另外,只是指出苹果文档建议使用 if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_6_1) {} else {} 检查。干杯!
非常感谢。你的代码对我们很有帮助。请解释一下 viewWillLayoutSubviews 函数。
M
Mandeep Pasbola

要在 ios7 中隐藏状态栏,请执行以下简单步骤:

在 Xcode 中转到“Resources”文件夹并打开“(app name)-Info.plist file”。

检查“基于视图控制器的状态栏外观”键并将其值设置为“否”

检查“状态栏最初隐藏”键并将其值设置为“是”

如果键不存在,那么您可以通过选择顶部的“information property list”并单击 + 图标来添加它


看清楚问题,他并没有要求完全隐藏状态栏。
@AspersionCast:他问“有没有办法避免这种情况?”这是避免它的方法之一。
C
Community

如果你想完全隐藏它并避免处理它,这很好用。

-(BOOL) prefersStatusBarHidden
{
    return YES;
}

参考https://stackoverflow.com/a/18873777/1030449


t
tipycalFlow

如果使用 xib,一个非常简单的实现是将所有子视图封装在一个容器视图中,并带有调整大小标志(您已经使用它来实现 3.5" 和 4" 的兼容性),以便视图层次结构看起来像这样

https://i.stack.imgur.com/iJkfp.png

然后在 viewDidLoad 中,执行以下操作:

- (void)viewDidLoad
{
  [super viewDidLoad];
  // initializations
  if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) // only for iOS 7 and above
  {
    CGRect frame = containerView.frame;
    frame.origin.y += 20;
    frame.size.height -= 20;
    containerView.frame = frame;
  }
}

这样,无需针对 iOS 7 兼容性修改笔尖。如果你有背景,可以把它放在containerView之外,让它覆盖整个屏幕。


T
Tony

https://i.stack.imgur.com/RsCCW.png


S
Saru

对于导航栏:

编写此代码:

self.navigationController.navigationBar.translucent = NO;

只是为我做了伎俩。


R
RamaKrishna Chunduri

文森特的回答 edgeForExtendedLayout 对我有用。

这些宏有助于确定操作系统版本,使其更容易

// 7.0 and above 
#define IS_DEVICE_RUNNING_IOS_7_AND_ABOVE() ([[[UIDevice currentDevice] systemVersion] compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending) 

// 6.0, 6.0.x, 6.1, 6.1.x
#define IS_DEVICE_RUNNING_IOS_6_OR_BELOW() ([[[UIDevice currentDevice] systemVersion] compare:@"6.2" options:NSNumericSearch] != NSOrderedDescending) 

将这些宏添加到项目的 prefix.pch 文件中,并且可以在任何地方访问

if(IS_DEVICE_RUNNING_IOS_7_AND_ABOVE())
{
 //some iOS 7 stuff
 self.edgesForExtendedLayout = UIRectEdgeNone;
}

if(IS_DEVICE_RUNNING_IOS_6_OR_BELOW())
{
 // some old iOS stuff
}

对我来说 self.edgesForExtendedLayout = UIRectEdgeNone;不工作......有什么理由吗?
s
stema

我已经将我的答案发布到另一篇与这个问题相同的帖子中。

来自 Apple iOS7 过渡指南,https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TransitionGuide/AppearanceCustomization.html#//apple_ref/doc/uid/TP40013174-CH15-SW1

当我不想重叠并且我有 tableviewcontroller 时,特别是 automaticallyAdjustsScrollViewInsets=YESset self.edgesForExtendedLayout = UIRectEdgeNone 对我有用。


A
Ali Shahid

如果您希望不惜一切代价启用“使用自动布局”,请将以下代码放在 viewdidload.xml 中。

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) 
{
        self.edgesForExtendedLayout = UIRectEdgeNone;
        self.extendedLayoutIncludesOpaqueBars = NO;
        self.automaticallyAdjustsScrollViewInsets = NO;
}

J
John Pang

从 YTPlayer 的横向视图返回后,我的状态栏和导航栏重叠。这是我尝试@comonitos 的版本后的解决方案,但不适用于我的 iOS 8

- (void)fixNavigationBarPosition {
    if (self.navigationController) {
        CGRect frame = self.navigationController.navigationBar.frame;
        if (frame.origin.y != 20.f) {
            frame.origin.y = 20.f;
            self.navigationController.navigationBar.frame = frame;
        }
    }
}

只要你想固定导航栏的位置,就调用这个函数。我调用了 YTPlayerViewDelegate 的 playerView:didChangeToState:

- (void)playerView:(YTPlayerView *)playerView didChangeToState:(YTPlayerState)state {
    switch (state) {
        case kYTPlayerStatePaused:
        case kYTPlayerStateEnded:
            [self fixNavigationBarPosition];
            break;
        default:
    }
}