的开发者, 我在界面生成器(Xcode 5 / iOS 7)中的自动布局遇到了麻烦。 这是非常基础和重要的,所以我认为每个人都应该知道这是如何正确工作的。如果这是Xcode中的一个bug,那它就是一个严重的bug !

所以,每当我有这样的视图层次结构时,我就会遇到麻烦:

>UIViewController
>> UIView
>>>UIScrollView
>>>>UILabel (or any other comparable UIKit Element)

UIScrollView有固定的约束,例如,每边50px(没问题)。 然后我添加一个顶部空间约束UILabel(没有问题)(我甚至可以钉标签的高度/宽度,改变什么,但应该是不必要的,由于标签的内在大小)

当我给UILabel添加一个尾随约束时,问题就开始了:

例如,尾随空间到:Superview等于:25

现在出现了两个警告——我不明白为什么:

A)滚动内容大小不明确(滚动视图具有不明确的滚动内容高度/宽度)

B)视图错位(Label Expected: x= -67 Actual: x= 207)

我在一个新项目中做了这个最小的例子,你可以下载,我附上了一张截图。如你所见,Interface Builder期望Label位于UIScrollView的边界之外(橙色虚线矩形)。用解决问题工具更新标签的框架,将其移到那里。

请注意:如果你用一个UIView替换UIScrollView,行为是预期的(标签的帧是正确的,根据约束)。所以看起来要么是UIScrollView有问题,要么是我错过了一些重要的东西。

当我运行应用程序而不更新标签的框架时,它的位置很好,正是它应该在的地方,UIScrollView是可滚动的。 如果我确实更新了帧,标签就会从视野中消失,UIScrollView也不会滚动。

帮帮我,欧比王·克诺比!为什么是模棱两可的布局?为什么会出现这种错位的观点?

你可以在这里下载示例项目,试着看看你能弄清楚发生了什么: https://github.com/Wirsing84/AutoLayoutProblem


当前回答

我通过使用“解决自动布局问题”>“为所选视图添加缺失约束”来解决我的视图的这种问题

以下两个约束条件可以解决我的问题:

trailing = Stack View.trailing - 10
bottom = Stack View.bottom + 76

中: 尾随,bottom是UIScrollView的尾随,底部

其他回答

import UIKit

class ViewController: UIViewController {

    //
    let scrollView: UIScrollView = {
        
        let sv = UIScrollView()
        sv.translatesAutoresizingMaskIntoConstraints = false
        return sv
    }()
    
    let lipsumLbl: UILabel = { // you can use here any of your subview
        
        let lbl = UILabel()
        lbl.translatesAutoresizingMaskIntoConstraints = false
        lbl.text = """
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce eleifend nisi sit amet mi aliquet, ut efficitur risus pellentesque. Phasellus nulla justo, scelerisque ut libero id, aliquet ullamcorper lectus. Integer id iaculis nibh. Duis feugiat mi vitae magna tincidunt, vitae consequat dui tempor. Donec blandit urna nec urna volutpat, sit amet sagittis massa fringilla. Pellentesque luctus erat nec dui luctus, sed maximus urna fermentum. Nullam purus nibh, cursus vel ex nec, pulvinar lobortis leo. Proin ac libero rhoncus, bibendum lorem sed, congue sapien. Donec commodo, est non mollis malesuada, nisi massa tempus ipsum, a varius quam lorem vitae nunc.
        
        Cras scelerisque nisi dolor, in gravida ex ornare a. Interdum et malesuada fames ac ante ipsum primis in faucibus. Maecenas vitae nisl id erat sollicitudin accumsan sit amet viverra sapien. Etiam scelerisque vulputate ante. Donec magna nibh, pharetra sed pretium ac, feugiat sit amet mi. Vestibulum in ipsum vitae dui vehicula pulvinar eget ut lectus. Fusce sagittis a elit ac elementum. Fusce iaculis nunc odio, at fermentum dolor varius et. Suspendisse consectetur congue massa non gravida. Sed id elit vitae nulla aliquam euismod. Pellentesque accumsan risus dolor, eu cursus nibh semper id.
        
        Vestibulum vel tortor tellus. Suspendisse potenti. Pellentesque id sapien eu augue placerat dictum. Fusce tempus ligula at diam lacinia congue in ut metus. Maecenas volutpat tellus in tellus maximus imperdiet. Integer dignissim condimentum lorem, id luctus nisi maximus at. Nulla pretium, est sit amet mollis eleifend, tellus nulla viverra dolor, ac feugiat massa risus a lectus. Pellentesque ut pulvinar urna, blandit gravida ipsum. Nullam volutpat arcu nec fringilla auctor. Integer egestas enim commodo, faucibus neque ac, rutrum magna. Vivamus tincidunt rutrum auctor. Cras at rutrum felis. Fusce elementum lorem ut pharetra venenatis.
        """
        lbl.textColor = .darkGray
        lbl.font = UIFont.systemFont(ofSize: 16)
        lbl.numberOfLines = 0
        return lbl
    }()
    
    //======================================================================//
    //
    // MARK:- viewDidLoad
    //
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupViews()
        setupAutoLayout()
    }
    
    func setupViews() {
        
        title = "ScrollView Demo"
        view.backgroundColor = .white
        view.addSubview(scrollView)
        scrollView.addSubview(lipsumLbl)
    }
    
    func setupAutoLayout() {
        
        scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        scrollView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        
        lipsumLbl.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        lipsumLbl.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        lipsumLbl.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        lipsumLbl.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    }
}

输出:

Xcode 11+, Swift 5

如果你想知道为什么所有的答案都不再工作了,请确保你已经固定了内容视图(你已经放在滚动视图内的那个)到滚动视图的内容布局指南,而不是框架布局指南。

内容视图边缘(前导,后拉,顶部,底部)不应该像图像-框架布局指南上的前导那样被固定

但像这样-内容布局指南。

然后大部分答案都会适用于你。

现在最简单的方法是这样的:

把滚动视图放到根视图中 将滚动视图的所有边固定在父视图上 取另一个UIView(我们称之为content view)把它放到滚动视图中 将内容视图的所有边固定在滚动视图的内容布局指南上 固定内容视图的宽度等于滚动视图的框架布局指南 以任何你想要的方式固定内容视图的高度(我在下面的例子中使用了常量高度约束)

总的来说,在最简单的实现中,你的结构是这样的

在我的情况下,我收到了不正确的内容大小和内容大小模糊的问题在iPad,但在iPhone的情况下工作。我在故事板中做了以下更改来解决这个问题。

在UIView中添加scrollview并添加约束前置,上,后,下到0,0,0,0。 设置滚动视图的高度根据要求,例如。One hundred. 添加UIView到滚动视图,并添加约束领先,顶部,尾部和底部0,0,0,0和对齐中心(X)和中心(Y)约束。 在滚动视图的尺寸检查器中取消选择“内容布局指南”。

我终于明白了,我希望这更容易理解。

你通常可以通过添加一个基本的UIView到滚动视图作为一个“内容视图”来绕过这个警告,就像他们提到的,让它和你的滚动视图一样大,在这个内容视图上,设置这6个参数。

如您所见,您总共需要6个参数!哪一个在正常情况下,你复制了两个约束,但这是避免故事板错误的方法。

更新

如今,苹果意识到我们多年前解决的问题(lol_face),并提供内容布局指南和框架布局指南作为UIScrollView的一部分。因此,您需要执行以下步骤:

与以下原始回复相同; 对于这个contentView,设置顶部,底部,左边和右边的边距为0,将它们固定到滚动视图的内容布局指南; 现在将contentView的高度设置为Frame Layout Guide的高度。对宽度做同样的操作; 最后,将等高约束的优先级设置为250(如果您需要视图垂直滚动,宽度水平滚动)。

完成了。

现在你可以在contentView中添加所有的视图,scrollView的contentSize会自动根据contentView调整大小。

不要忘记从contentView中最后一个对象的底部设置约束到contentView的边缘。

原始(弃用)

So I just sorted out in this way:

在UIScrollView里面添加一个UIView(我们可以称之为contentView); 在这个contentView中,将上,下,左,右边距设置为0(当然是从scrollView,也就是superView中);设置也对齐中心水平和垂直;