的开发者, 我在界面生成器(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


当前回答

我想这是10秒后的作品。我在XCode 7.3中观察到它,并制作了一个视频。检查:

https://www.youtube.com/watch?v=yETZKqdaPiI

你所要做的就是给UIScrollView添加一个宽度和高度相同的子视图。然后选择ViewController并按下Reset到建议的约束。为了更清楚地理解,请查看视频。

谢谢

其他回答

我也有同样的问题。取消这个复选框。因为您是在代码中设置内容大小。

This error took me a while to track down, initially I tried pinning the ScrollView's size but the error message clearly says "content size". I made sure everything I pinned from the top of the ScrollView was also pinned to the bottom. That way the ScrollView can calculate its content height by finding the height of all the objects & constraints. This solved the ambiguous content height, the width is pretty similar... Initially I had most things X centered in the ScrollView, but I had to also pin the objects to the side of the ScrollView. I don't like this because the iPhone6 might have a wider screen but it will remove the 'ambiguous content width' error.

使用自动布局

在一个定义良好的视图中添加滚动视图,然后在滚动视图中添加堆栈视图

从滚动视图和堆栈视图中添加上、左、右、下、中心X和中心Y约束到相关的超级视图中

确保约束从堆栈视图链接到正确的父视图(scrollview),因为当前默认设置是添加Align Top约束,而不是Top Space约束。

我知道我可能晚了,但是下一个解决方案无需额外的代码就解决了这类问题,只是使用故事板:

对于你的内容视图,你需要设置前/后/上/下空格到滚动视图的约束,这不会改变内容视图框架,如下所示:

当然,您需要为内容视图创建额外的约束,以便滚动视图可以知道内容大小。例如,设置固定高度和中心x。

希望这能有所帮助。

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
    }
}

输出: