尽管添加了自动布局约束,但 UIScrollView 不滚动

Posted

技术标签:

【中文标题】尽管添加了自动布局约束,但 UIScrollView 不滚动【英文标题】:UIScrollView not scrolling despite adding Auto Layout constraints 【发布时间】:2017-06-14 18:54:29 【问题描述】:

我正在开发一个项目,在该项目中我将多个 UITextFields 添加到 UIView,它充当容器视图。然后我将此容器视图添加到 UIScrollView,然后我将其添加到屏幕的主视图中。问题是,我的容器视图出现在屏幕上,但不滚动,尽管附加到 UIScrollView,我不知道为什么。所有的代码和约束都在 Swift 中。

以下是我目前掌握的相关代码:

private func setupViews() 
        view.backgroundColor = .nzRedColor()

        registerView.frame = CGRect(x: 0.0, y: 0.0, width: self.view.frame.width, height: self.view.frame.height)
        registerView.backgroundColor = UIColor.green

        registerScrollView.frame = CGRect(x: 0.0, y: 0.0, width: self.view.frame.width, height: 300.0)
        registerScrollView.backgroundColor = UIColor.blue


        let addViewsClosure =  (superview: UIView, views: UIView...)->() in
            for view in views 
                view.translatesAutoresizingMaskIntoConstraints = false
                if ((view as? UIImageView) != nil) 
                    superview.addSubview(view)
                 else if ((view as? UITextField) != nil) 
                    self.registerView.addSubview(view)
                    self.registerScrollView.addSubview(self.registerView)
                    superview.addSubview(self.registerScrollView)
                 else 
                    superview.addSubview(view)
                
            
        

        let customizeTextFields =  (textfields: UITextField...) in
            for textfield in textfields 
                textfield.backgroundColor = UIColor(white: 1.0, alpha: 0.3)
                textfield.font = UIFont.systemFont(ofSize: 14, weight: UIFontWeightRegular)
                textfield.layer.cornerRadius = 2.0
            
        

        customizeTextFields(firstNameTextField, lastNameTextField, cityTextField, countryTextField, emailTextField, passwordTextField, passwordConfirmationTextField)


        addViewsClosure(view, logoImageView, firstNameTextField, lastNameTextField, cityTextField, countryTextField, emailTextField, passwordTextField, passwordConfirmationTextField, registerButton, skipButton)


        logoImageView.constrainTop(at: 50, after: topLayoutGuide.anchorableRepresentation)
        logoImageView.constrainCenterHorizontally()
        logoImageWidthConstraint = logoImageView.constrainWidth(at: 0)
        logoImageHeightConstraint = logoImageView.constrainHeight(at: 0)
        updateLogoImageSize()


        firstNameTextField.constrainTop(at: 10, after: logoImageView)
        firstNameTextField.constrainHeight(at: 50)
        firstNameTextField.constrainLeading(alignedWith: view, offset: 10)
        firstNameTextField.constrainTrailing(alignedWith: view, offset: -10)

        lastNameTextField.constrainTop(at: 10, after: firstNameTextField)
        lastNameTextField.constrainHeight(at: 50)
        lastNameTextField.constrainLeading(alignedWith: firstNameTextField)
        lastNameTextField.constrainTrailing(alignedWith: firstNameTextField)

        cityTextField.constrainTop(at: 10, after: lastNameTextField)
        cityTextField.constrainHeight(at: 50)
        cityTextField.constrainLeading(alignedWith: firstNameTextField)
        cityTextField.constrainTrailing(alignedWith: firstNameTextField)

        countryTextField.constrainTop(at: 10, after: cityTextField)
        countryTextField.constrainHeight(at: 50)
        countryTextField.constrainLeading(alignedWith: firstNameTextField)
        countryTextField.constrainTrailing(alignedWith: firstNameTextField)

        emailTextField.constrainTop(at: 10, after: countryTextField)
        emailTextField.constrainHeight(at: 50)
        emailTextField.constrainLeading(alignedWith: firstNameTextField)
        emailTextField.constrainTrailing(alignedWith: firstNameTextField)

        passwordTextField.constrainTop(at: 10, after: emailTextField)
        passwordTextField.constrainHeight(at: 50)
        passwordTextField.constrainLeading(alignedWith: firstNameTextField)
        passwordTextField.constrainTrailing(alignedWith: firstNameTextField)

        passwordConfirmationTextField.constrainTop(at: 10, after: passwordTextField)
        passwordConfirmationTextField.constrainHeight(at: 50)
        passwordConfirmationTextField.constrainLeading(alignedWith: firstNameTextField)
        passwordConfirmationTextField.constrainTrailing(alignedWith: firstNameTextField)

        registerView.constrainTop(at: 0)
        registerView.constrainHeight(at: self.view.frame.height)
        registerView.constrainLeading(at: 0)
        registerView.constrainTrailing(at: 0)

        registerScrollView.constrainTop(at: 50, after: logoImageView)
        registerScrollView.constrainHeight(at: 300.0)
        registerScrollView.constrainLeading(at: 0)
        registerScrollView.constrainTrailing(at: 0)

        registerButton.constrainTop(at: 30, after: passwordConfirmationTextField)
        registerButton.constrainHeight(at: 50)
        registerButton.constrainLeading(alignedWith: firstNameTextField)
        registerButton.constrainTrailing(alignedWith: firstNameTextField)

        skipButton <-  $0.top >= registerButton.anchors.bottom + 12 
        skipButton.constrainBottom(at: 12)
        skipButton.constrainCenterHorizontally()
    

我想在这里注意两点:

    尽管我将 registerView 的背景颜色设置为“绿色”,但我没有显示视图。

    由于某种原因,所有的 UITextFields 都直接出现在 UIScrollView 上(因为它的颜色是蓝色的),并且 UIScrollView 是可见的,但遗憾的是不能滚动。谁能看到我做错了什么?

【问题讨论】:

第一个建议:尝试在新的视图/项目中复制它,但可能只有 2 个子视图,这样您就可以清楚地调查发生了什么。 【参考方案1】:

当使用滚动视图的自动布局时,滚动视图的内容定义了.contentSize。这意味着您的registerView 必须正确设置所有约束。

您将registerView 背景设置为绿色,但您看不到视图?我敢打赌,如果您将其 .clipsToBounds 设置为 true,您也不会再看到文本字段了。

    registerView.constrainTop(at: 0)
    registerView.constrainHeight(at: self.view.frame.height)
    registerView.constrainLeading(at: 0)
    registerView.constrainTrailing(at: 0)

您已经设置了 Top、Leading、Trailing 和 Height 约束 - 但看起来您缺少 Width 和 Bottom。

Bottom 约束可能应该设置为 0 - 像 Top、Leading 和 Trailing。

我猜你希望 registerView 高度约束由最后一个文本字段 - passwordConfirmationTextField 确定 - 但如果是这种情况,你仍然缺少那个。

【讨论】:

非常感谢您的回答。听从您的建议后,我现在可以看到 registerView 的绿色背景色了!但是,我的 textFields 没有随着 registerView 滚动。它们似乎卡在 registerView 后面的 scrollView 上。我是否正确地假设在我纠正了与它们相关的约束问题之后 textFields 将正确滚动? 不确定...如果您使用 Debug Hierarchy 检查,TextFields 子视图是 registerView 还是 registerScrollView?而且,尺寸显示是否正确? textFields是registerView的子视图,而registerView是scrollView的子视图。不幸的是,没有,文本字段的大小显示不正确。 如果你有这个“可共享”的形式,我很乐意快速浏览一下。但是,我会回到我最初的评论:尝试降低复杂性以帮助您弄清楚发生了什么。 如何直接与您分享?

以上是关于尽管添加了自动布局约束,但 UIScrollView 不滚动的主要内容,如果未能解决你的问题,请参考以下文章

自动布局和约束不使按钮大小相同(尽管有大小限制)

如何获得影响给定子视图的自动布局约束?

自动布局约束不起作用

您可以使用自动布局添加派生约束吗?

添加约束时缺少自动布局“安全区域”

在自定义 UITableViewCell 中忽略自动布局