【问题标题】:iOS 11 Layout guidance about safe Area for iPhone xiOS 11 iPhone x 安全区域布局指南
【发布时间】:2018-03-02 19:59:11
【问题描述】:

我的应用程序已经在应用商店中,昨天我将我的 Xcode 版本更新到了 9,并且除了 iPhone x 之外都可以正常工作。 UI 崩溃了。

1.这里我创建了两个 UIView(均为固定高度),分别命名为 Header 和 Tab bar,并且我隐藏了我的 NavigationBar 整个应用程序。

2.为UIViewController添加扩展,用于制作HeaderTab bar

func addHeaderTab(currentViewController:UIViewController,content:String, isMenu:Bool){
        let noView = TopHeaderView()
        noView.tag = 12345
        noView.isMenu = isMenu
        noView.translatesAutoresizingMaskIntoConstraints = false
        currentViewController.view .addSubview(noView)
        if isMenu{
            noView.menuBtn .setImage(UIImage(named: "Small"), for: .normal)
            noView.logoImg.isHidden = false

        }else{
            noView.menuBtn .setImage(UIImage(named: "arrow_small"), for: .normal)
            noView.logoImg.isHidden = true
        }
        noView.titleLbl.text = content
        noView.delegate = (currentViewController as! menuOpen)

        NSLayoutConstraint(item: noView, attribute: .leading, relatedBy: .equal, toItem: currentViewController.view, attribute: .leading, multiplier: 1.0, constant: 0.0).isActive = true

        NSLayoutConstraint(item: noView, attribute: .trailing, relatedBy: .equal, toItem: currentViewController.view, attribute: .trailing, multiplier: 1.0, constant: 0.0).isActive = true

        NSLayoutConstraint(item: noView, attribute: .top, relatedBy: .equal, toItem: currentViewController.view, attribute: .top, multiplier: 1.0, constant: 0.0).isActive = true

        NSLayoutConstraint(item: noView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: 64).isActive = true

    }

并在每个 Viewcontroller 中调用它,如下所示:

self.addHeaderTab(currentViewController: self, content:"நிகழ்ச்சி நிரல்" , isMenu: true)

就像那个标签栏我也做过,但所有设备都可以正常工作,预计 iPhone x

查看我的屏幕截图:

我研究过https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/

但不清楚他们的文件。

我们将不胜感激,在此先感谢。

【问题讨论】:

    标签: ios autolayout swift4 xcode9 iphone-x


    【解决方案1】:

    随着 iOS11(以及 iPhoneX 的出现)Apple 引入了安全区域布局指南,以使您的视图适应 iPhoneX。

    安全区域是屏幕上未被凹槽或主页指示器重叠的区域。

    为避免您遇到的问题,您必须更改 iOS11 的 noView 顶部约束:

    if #available(iOS 11, *) {
       let guide = view.safeAreaLayoutGuide
       NSLayoutConstraint.activate([
          noView.topAnchor.constraint(equalTo: guide.topAnchor)
       ])
    } else {
       NSLayoutConstraint.activate([
          noView.topAnchor.constraint(equalTo: currentViewController.topLayoutGuide.bottomAnchor)
       ])
    }
    NSLayoutConstraint.activate([
       noView.leadingAnchor.constraint(equalTo: currentViewController.view.leadingAnchor),
       noView.trailingAnchor.constraint(equalTo: currentViewController.view.trailingAnchor),
       noView.heightAnchor.constraint(equalToConstant: 65)
    ])
    

    不幸的是,这还不是全部。因为现在您的noView 在 iPhone X 上向下移动,但状态栏不再有红色背景。您在状态栏后面添加了红色背景色:

    您可以使用 UINavigationController(带有红色导航栏)让事情变得更简单:

    使用这种方法,您不必设置任何约束!系统会自动为您进行所有调整。

    【讨论】:

    • 你帮了大忙,非常感谢..有没有办法将自定义 UIView 加载到导航栏中?如果是,就没有问题,对吗?你对此有什么想法吗
    • 当然,您可以使用视图控制器的UINavigationItem 自定义导航栏(当您的视图控制器嵌入到导航控制器中时)。您可以添加按钮项和标题视图(可以是任何UIView)。看看这些文档:developer.apple.com/documentation/uikit/uinavigationitem
    • 我尝试将 xib 和子视图加载到标题视图,但不能正常工作
    • @3000 我不建议插入一个新的UIViewController。我建议 OP 应该使用 UINavigationController 而不是构建自己的自定义导航栏。这就是UINavigationController 的用途;-)
    • @3000 如果只是在顶部显示一个图标,我完全同意。然后我只会使用UIView 而不是UINavigationBar。但是在 OP 的示例中,有一个菜单图标,因此肯定会发生一些导航。这就是为什么我会在这里使用UINavigationController
    【解决方案2】:

    在 iPhone-X 上,在 Objective-C 中用于顶部和底部边距

    if (@available(iOS 11, *)) {
    
        NSLayoutConstraint *bottomConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                              attribute:NSLayoutAttributeBottom
                                                                              relatedBy:NSLayoutRelationEqual
                                                                                 toItem:self.parentView.safeAreaLayoutGuide
                                                                              attribute:NSLayoutAttributeBottom
                                                                             multiplier:1.0
                                                                               constant:0];
    
    
        NSLayoutConstraint *topConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                       attribute:NSLayoutAttributeTop
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:self.parentView.safeAreaLayoutGuide
                                                                       attribute:NSLayoutAttributeTop
                                                                      multiplier:1.0
                                                                        constant:0];
    
    
    } else {
    
        NSLayoutConstraint *bottomConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                          attribute:NSLayoutAttributeBottom
                                                                          relatedBy:NSLayoutRelationEqual
                                                                             toItem:self.parentView
                                                                          attribute:NSLayoutAttributeBottom
                                                                         multiplier:1.0
                                                                           constant:0];
    
    
        NSLayoutConstraint *topConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                       attribute:NSLayoutAttributeTop
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:self.parentView
                                                                       attribute:NSLayoutAttributeTop
                                                                      multiplier:1.0
                                                                        constant:0];
    
    }
    

    【讨论】:

      【解决方案3】:

      如果您不想使用UINavigationController,但想要有一个导航栏,您可以这样做(使用UIImageView):

      https://medium.com/@kahseng.lee123/creating-custom-navigation-bar-tab-bar-for-iphone-x-f03b1e1827d3

      或者您可以创建一个视图并将其顶部约束设置为超级视图的顶部,并将其底部约束设置为导航栏的顶部。别忘了把它变成红色。 :-)

      【讨论】:

        【解决方案4】:

        根据设备设置headerView的高度约束。

        if iPhoneX {
        NSLayoutConstraint(item: noView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: 64+24).isActive = true
        } else {
        NSLayoutConstraint(item: noView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: 64).isActive = true
        }
        

        并将所有子视图的(headerView)约束分别设置到superview(headerView)的底部。

        关于我们为何为 iphoneX 添加 24 像素的补充说明:

            // portrait orientation - status bar is shown
            additionalSafeAreaInsets.top = 24.0
        

        【讨论】:

          猜你喜欢
          • 2018-06-26
          • 1970-01-01
          • 1970-01-01
          • 2018-02-28
          • 1970-01-01
          • 2018-03-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多