在iOS10

时间:2016-09-19 02:33:02

标签: ios9 ios10 nslayoutconstraint

我遇到UIScrollView上的约束问题,它似乎是iOS10特有的。我似乎在滚动视图的顶部和内部的内容视图之间有一个间隙,它应该粘在顶部。

iOS 9上似乎没有任何差距,但在iOS 10上会出现差距 为清楚起见,在两种情况下,滚动视图顶部都固定在顶部布局指南的底部,该指南与导航栏的底部完美对齐。 iOS 10在滚动视图顶部和内容视图顶部之间引入了导航栏大小的间隙。

我可以将滚动视图的顶部与顶部布局指南的顶部对齐,这会将间隙放在导航栏下方,内容视图排列正常,但在iOS 9上,内容视图将位于导航栏是不受欢迎的。

我已经快速创建了一些操场代码,以演示下面的问题。有什么明显的东西我不见了吗?在iOS 10中发生了什么变化使这成为一个问题,我该如何解决它?

comparison of screenshots from iPhone 5s simulator

import UIKit
import PlaygroundSupport

class TestViewController: UIViewController {
    var mainScrollView: UIScrollView
    var contentView: UIView

    init() {
        self.mainScrollView = UIScrollView()
        self.contentView = UIView()

        super.init(nibName: nil, bundle: nil)

        self.view.backgroundColor = UIColor.white
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        self.mainScrollView.backgroundColor = UIColor.green
        self.contentView.backgroundColor = UIColor.blue

        self.mainScrollView.translatesAutoresizingMaskIntoConstraints = false
        self.contentView.translatesAutoresizingMaskIntoConstraints = false

        self.view.addSubview(self.mainScrollView)
        self.mainScrollView.addSubview(self.contentView)

        // constrain the scroll view bounds to the view
        self.view.addConstraint(NSLayoutConstraint(item: self.mainScrollView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.topLayoutGuide, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0))
        self.view.addConstraint(NSLayoutConstraint(item: self.mainScrollView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.bottomLayoutGuide, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0))
        self.view.addConstraint(NSLayoutConstraint(item: self.mainScrollView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 0))
        self.view.addConstraint(NSLayoutConstraint(item: self.mainScrollView, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0))

        // constrain the content view bounds to the scroll view
        self.mainScrollView.addConstraint(NSLayoutConstraint(item: self.contentView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.mainScrollView, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0))
        self.mainScrollView.addConstraint(NSLayoutConstraint(item: self.contentView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.mainScrollView, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0))
        self.mainScrollView.addConstraint(NSLayoutConstraint(item: self.contentView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.mainScrollView, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 0))
        self.mainScrollView.addConstraint(NSLayoutConstraint(item: self.contentView, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: self.mainScrollView, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0))

        // constrain the content view's size to the view's size
        self.view.addConstraint(NSLayoutConstraint(item: self.contentView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0))
        self.view.addConstraint(NSLayoutConstraint(item: self.contentView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.greaterThanOrEqual, toItem: self.view, attribute: NSLayoutAttribute.height, multiplier: 1, constant: 0))
    }
}

let rootViewController = TestViewController()
rootViewController.title = "Test"

let navigationController = UINavigationController(rootViewController: rootViewController)
PlaygroundPage.current.liveView = navigationController.view

2 个答案:

答案 0 :(得分:1)

在您设置的第一个约束中,您将其设置为topLayoutGuide bottom。因此,从Apple documentation bottom的{​​{1}}取决于您堆叠子视图的方式。因此,在您的示例中,如果将其设置为

topLayoutGuide它有效。

但我经常使用我的子视图的顶部,所以我没有“保证金”。所以它看起来像:self.view.addConstraint(NSLayoutConstraint(item: self.mainScrollView, attribute: .top, relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .top, multiplier: 1, constant: 0))

希望它有所帮助。

答案 1 :(得分:0)

我有同样的问题,在我的情况下是一个UISearchController,其中视图的添加是动态完成的,所以我没有机会添加约束。我只需要手动设置滚动视图的contentInset(在我的例子中是一个表格视图)并将其设置为距离所需屏幕顶部的距离。对你来说,它可能看起来像这样:

// status bar + nav bar = 64
self.mainScrollView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
self.view.automaticallyAdjustsScrollViewInsets = NO;

请注意我从我的Obj中迅速改编。 C代码如果稍微关闭就会道歉。我在iOS 9和10中进行了测试,看起来两者都是正确的。