iOS 7状态栏与导航栏碰撞

时间:2013-09-30 23:55:06

标签: ios objective-c uinavigationcontroller uinavigationbar ios7

我的应用中有一个视图控制器,在故事板中拖动了导航栏。它在iOS 6中运行良好,但在iOS 7中它看起来像这样:

ios 7 status bar nav var

状态栏和导航栏不应相互冲突。我已经看到很多关于堆栈溢出的问题,但它们对我没什么帮助。

有些问题说我应该使用这个“self.edgesForExtendedLayout = UIRectEdgeNone;”但它不起作用。有人说我应该删除导航栏并将其嵌入导航控制器中,由于我的程序实现方式,我无法做到这一点。一些解决方案建议使用视图边界,但它也不适用于我。

有什么能帮我解决这个问题。提前谢谢!

更新:我已将视图控制器嵌入到uinavigation控制器中。删除了之前手动添加的导航栏。现在它在故事板中看起来不错,但是当我运行它时,它显示以下内容:

iOS 7 Navigation Status bar

它显示来自其后面的另一个视图控制器的文本,即其父视图控制器。意味着它现在透明。谁能指出我做错了什么?

17 个答案:

答案 0 :(得分:66)

最新版本的iOS带来了许多视觉上的变化,从开发人员的角度来看,导航和状态栏是两个显着的变化。

状态栏现在是透明的,后面的导航栏显示出来。导航栏图像甚至可以扩展到状态栏后面。

首先,如果您是初学者并且刚刚开始iOS开发并且对状态栏和导航栏的工作方式感到困惑,您可以简单地浏览我发现非常有用的博客文章HERE。它包含iOS 7中与导航和状态栏相关的所有信息。

现在回答你的问题。首先,我可以看到两个不同的问题。一个是您的状态栏和导航栏都是相互碰撞的,如您在带图像的问题中所示。

问题:问题是您之前已经在视图控制器中拖动了导航栏,该导航栏在iOS 6中正常工作但随着iOS 7 SDK的到来,这种方法导致了状态栏和导航栏相互重叠。

第一个问题的解决方案:您可以使用UIBarPositionTopAttached或者您可以使用视图边界和框架,我也可以建议并链接到Apple's documentation和bla bla bla但是这需要有一段时间你可以解决这个问题。

解决此问题的最佳和最简单的方法是将视图控制器嵌入到导航控制器中,就是这样。您可以通过选择视图控制器并转到编辑器>来完成。嵌入>导航控制器。 (如果旧导航栏上有任何内容,您可以先将其拖放,将视图控制器嵌入导航控制器,然后移动新导航栏上的栏按钮,然后删除旧导航栏)

第二个问题的解决方案:此解决方案适用于您在更新中提及的特定问题,而不是一般公众阅读此问题。如您所见,导航和状态栏不可见,透明区域显示父视图控制器。我并不真正使用你为什么面对这个问题,但很可能是因为某些第三方库,如ECSlidingView或任何其他涉及。您可以在故事板中选择此视图控制器,并将视图的背景颜色设置为与导航栏相同。这将停止显示后面的父视图控制器,您的导航栏和状态栏将开始显示。现在,您可以使用文本视图覆盖视图控制器的其余部分,或者在其中使用的内容。

希望这有帮助!

答案 1 :(得分:33)

导航栏太靠近状态栏,因为从iOS 7开始,状态栏更多地覆盖整个视图控制器的视图。由于导航栏位于(0,0),状态栏将显示在导航栏的顶部。要解决此问题,只需向下移动导航栏(或者,如其他人所说),在导航栏和topLayoutGuide之间创建约束。

当你这样做时,你会发现导航栏和屏幕顶部之间有20点的间隙。那是因为你刚刚将导航栏向下移动了20个点。 “但是UINavigationController可以做得对!”当然,它是通过在视图控制器上实现UIBarPositioningDelegate来实现的。这是一种单方法协议,应该像这样实现:

- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar {
    return UIBarPositionTopAttached;
}

将视图控制器添加为导航栏的代理后,您会注意到导航栏仍然向下移动了20个点,但其背景将在状态栏下方向上延伸,就像在UINavigationController中一样。

您看到的另一件事是导航栏是半透明的,这意味着导航栏下方的任何内容都会在某种程度上可见。默认情况下,在iOS 7上,translucent上的UINavigationBar属性设置为YES。在iOS 7之前,默认值为NO

答案 2 :(得分:4)

你可以这样做:

1)在导航栏顶部布局指南之间添加约束(选择navigationBar,按住Ctrl键并转到底部布局指南,取消保留ctrl键)

Add vertical Contrain

2)选择垂直间距

vertical spacing

3)将常数设为 0

vertical spacing constant

<强>结果:

result

<强>更新

在AppDelegate文件中,您可以添加:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
{
  // Prevent Navigationbar to cover the view
  UINavigationBar.appearance().translucent = false
}

答案 3 :(得分:3)

我建议您在viewDidLoad方法中尝试:

self.navigationController.navigationBar.translucent = NO;

(默认情况下,现在是)

https://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationBar_Class/Reference/UINavigationBar.html#//apple_ref/occ/instp/UINavigationBar/translucent

答案 4 :(得分:2)

这对我有用,我希望你也有同样的运气:)。
在您的视图中添加以下代码。

-(void) viewDidLayoutSubviews
{
    CGRect tmpFram = self.navigationController.navigationBar.frame;
    tmpFram.origin.y += 20;
    self.navigationController.navigationBar.frame = tmpFram;
}

它基本上改变了导航栏的位置。

答案 5 :(得分:2)

  

使用Swift

正如@Scott Berrevoets在他的回答中所说,你需要在协议positionForBar中实现方法UIBarPositioningDelegate,但正如UINavigationBarDelegate协议实现了这个协议:

public protocol UINavigationBarDelegate : UIBarPositioningDelegate {
   ...
}

您只需要设置使用Storyboard设置的delegate的{​​{1}}并实施该方法,就像这样:

UINavigationBar

注意: 值得一提的是,如果设置导航栏的 y轴的位置,让我们从顶部开始说是40,那么它将从这个位置向下延伸到顶部,以模拟行为您需要从顶部设置为class ViewController: UIViewController, UINavigationBarDelegate { @IBOutlet weak var navigationBar: UINavigationBar! override func viewDidLoad() { super.viewDidLoad() self.navigationBar.delegate = self } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func positionForBar(bar: UIBarPositioning) -> UIBarPosition { return UIBarPosition.TopAttached } }

我希望它会对你有所帮助。

答案 6 :(得分:2)

如果您的UIViewController不在UINavigationController且您正在使用UIStoryBoard,则可以设置&#34; iOS 6/7 Deltas&#34;对于每个需要偏离UIStatusBar

的子视图,增量Y为20

enter image description here

答案 7 :(得分:2)

如果它仍然可以帮助某人,这对于我在ios 7及以上版本中移动导航栏的效果非常有用:

-(void)viewWillLayoutSubviews
{
    float iosVersion = 7.0;
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= iosVersion) {
        // iOS 7+
        CGRect viewFrame = self.view.frame;
        viewFrame.origin.y += 10;
        self.view.frame = viewFrame;
    }
}

在ios 6.1及以下的设备上,导航栏将保持不变,就像之前一样。

这就是我过去使状态栏的内容变亮的原因:

-(UIStatusBarStyle)preferredStatusBarStyle{
    return UIStatusBarStyleLightContent;
}

答案 8 :(得分:2)

这是IOS7的新功能。而不是盯着IOS7中的20 px导航栏盯着0 px。作为解决方案,将整个视图向下移动到20像素,或者您可以将图像用于高度为64像素的导航栏。

答案 9 :(得分:2)

首先,在Info.plist中将UIViewControllerBasedStatusBarAppearance设置为NO。 然后,在AppDelegate的{​​{1}}方法中添加:

application:didFinishLaunchingWithOptions:

答案 10 :(得分:1)

在早期iOS窗口中启动状态栏后,在iOS 7窗口中从早期版本的0px开始,视图高度为460(iPhone 4s及更早版本)和548(iPhone 5),但在iOS 7中,视图高度为480(iPhone 4s及更早版本) )和568(iPhone 5及更高版本),所以你必须在2o px之后开始视图排列,或者你必须从20px开始查看。

你可以在rootviewcontroller或所有viewcontroller中为代码视图从20px写下面的代码

#define IOS7_HEIGHT             64

- (void)viewDidLayoutSubviews {
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    if ([currSysVer compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending)
    {
        CGRect frame=[self.view frame];
        if (frame.origin.y!=IOS7_HEIGHT) {

            frame.origin.y = IOS7_HEIGHT;
            frame.size.height -= IOS7_HEIGHT;
            [self.view setFrame:frame];
            [self.view layoutSubviews];
        }
    }
}

此处高度为64,因为状态栏为20,导航栏为44。 尝试以下代码它会帮助你。你的问题将得到解决。

答案 11 :(得分:1)

在iOS 7中,应用占据屏幕尺寸的100%。这不是问题。 http://www.doubleencore.com/2013/09/developers-guide-to-the-ios-7-status-bar/

答案 12 :(得分:1)

对于那些在实施@Masterfego解决方案时遇到问题的人(也是官方解决方案,但我遇到了Xcode 6.3和自动约束的问题),这就是我所做的:

我有一个带有添加导航栏的UIViewController。我选择了NAvigation栏并添加了64px的高度限制。我们后来看到一个警告,导航栏会更高(但这就是我们所做的)。最后,您可以看到状态栏看起来很漂亮并且与导航栏颜色相同。 :)

PS:我还无法发布图片。

答案 13 :(得分:0)

这是最好的答案。 但我想知道如何使用Storyboard并在其上拖动UINavigationBar。 当我实现委托方法,并将返回结果设置为UIBarPositionTopAttached时,它不起作用。

- (void)viewDidLoad{
    self.navigationbar.delegate = self;
}
- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar{
    NSLog(@"Got it");
    //
    //    CGRect frame = self.navigaitonBar.frame;
    //
    //    frame = CGRectMake(0, 20, CGRectGetWidth(frame), CGRectGetHeight(frame));
    //    self.navigaitonBar.frame = frame;
    //
    //    NSLog(@"frame %f",frame.origin.y);
    return UIBarPositionTopAttached;
}

答案 14 :(得分:0)

如果你使用Xcode 6和Swift,你可以做到:

  1. 打开您应用的info.plist文件。
  2. 添加ViewControllerBasedStatusBarAppearance布尔键(如果它不存在)并指定值“NO”。
  3. 添加“状态栏样式”键(如果它不存在)并选择“不透明黑色样式”值。

答案 15 :(得分:0)

您可以创建附加到顶部布局指南的约束,以指定导航栏相对于状态栏的位置。有关使用布局指南的详细信息,请参阅iOS 7 UI Transition Guide: Appearance and Behavior section

答案 16 :(得分:0)

当我从ModalViewController打开全屏MainViewController时,我遇到了问题,当用户从{{1}返回NavigationBar时,MainViewController位置发生了变化}。

我注意到的问题是当用户回到ModalViewController时状态栏高度未被包括在内。请在返回MainViewController之前和之后调试并检查NavigationBar的来源。

ViewController

从viewWillAppear方法调用它 -

// This method will adjust navigation bar and view content.
    private func adjustNavigationControllerIfNeeded() {

        var frame = self.view.frame
        let navigationBarHeight = self.navigationController!.navigationBar.frame.size.height

        if(frame.origin.y == navigationBarHeight && !UIApplication.shared.isStatusBarHidden) { 

   // If status bar height is not included but it is showing then we have to adjust 
      our Navigation controller properly

            print("Adjusting navigation controller")
            let statusBarHeight = UIApplication.shared.statusBarFrame.height

            frame.origin.y += statusBarHeight // Start view below navigation bar
            frame.size.height -= statusBarHeight
            self.view.frame = frame

            self.navigationController!.navigationBar.frame.origin.y = statusBarHeight // Move navigation bar
        }
    }