【问题标题】:ScrollView Won't Scroll AHHHScrollView 不会滚动 AHHH
【发布时间】:2015-07-08 16:02:49
【问题描述】:

对于我的一生,我无法弄清楚我做错了什么。我要做的就是将一堆文本字段放在滚动视图中,并让它使用自动布局从本质上确定 contentSize。与我在那里观看和阅读的其他教程不同,我尝试以编程方式完成此操作,而不是通过 Storyboard 或 Xibs。

我在滚动视图中的每个视图(包括滚动视图本身)上都调用了setTranslatesAutoresizingMaskIntoConstraints(false)

我已经设置了滚动视图的heightwidth 以匹配它的超级视图,甚至将滚动视图定位在它的超级视图的中心(我读到有时你需要这样做才能让它工作)

我已将内容视图的边缘固定到其父视图(滚动视图)的 topleadingtrailingbottom 边缘

这是我的代码:

class ViewController: UIViewController {

    var scrollView = UIScrollView()
    var contentView = UIView()

    var textField1 = CustomTextField()
    var textField2 = CustomTextField()
    var textField3 = CustomTextField()
    var textField4 = CustomTextField()
    var textField5 = CustomTextField()
    var textField6 = CustomTextField()

    override func viewDidLoad() {
        super.viewDidLoad()

        scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
        contentView.setTranslatesAutoresizingMaskIntoConstraints(false)
        textField1.setTranslatesAutoresizingMaskIntoConstraints(false)
        textField2.setTranslatesAutoresizingMaskIntoConstraints(false)
        textField3.setTranslatesAutoresizingMaskIntoConstraints(false)
        textField4.setTranslatesAutoresizingMaskIntoConstraints(false)
        textField5.setTranslatesAutoresizingMaskIntoConstraints(false)
        textField6.setTranslatesAutoresizingMaskIntoConstraints(false)

        view.addSubview(scrollView)
        scrollView.addSubview(contentView)
        contentView.addSubview(textField1)
        contentView.addSubview(textField2)
        contentView.addSubview(textField3)
        contentView.addSubview(textField4)
        contentView.addSubview(textField5)
        contentView.addSubview(textField6)

        contentView.backgroundColor = .redColor()

        setupConstraints()
    }

    func setupConstraints() {
        // Install height and width constraints on our scroll view
        let heightLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0)
        let widthLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0)
        self.view.addConstraints([heightLC,widthLC])

        // Install centering constraints on our scroll view
        let centerXLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1.0, constant: 0)
        let centerYLC : NSLayoutConstraint = NSLayoutConstraint(item: scrollView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1.0, constant: 0)
        self.view.addConstraints([centerXLC,centerYLC])

        // Set the content view so it resizes with the same proportions on screen rotations //
        let contentViewTopLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
        let contentViewLeadingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)
        let contentViewTrailingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)
        let contentViewBottomLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
        let contentViewWidthLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0)
        let contentViewHeightLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0)
        scrollView.addConstraints([contentViewTopLC,contentViewLeadingLC,contentViewTrailingLC,contentViewBottomLC,contentViewWidthLC,contentViewHeightLC])

        // Setup the text field constraints
        let textField1Top : NSLayoutConstraint = NSLayoutConstraint(item: textField1, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
        let textField1Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField1, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
        let textField1Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField1, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
        contentView.addConstraints([textField1Top, textField1Leading, textField1Trailing])

        let textField2Top : NSLayoutConstraint = NSLayoutConstraint(item: textField2, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField1, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
        let textField2Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField2, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
        let textField2Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField2, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
        contentView.addConstraints([textField2Top, textField2Leading, textField2Trailing])

        let textField3Top : NSLayoutConstraint = NSLayoutConstraint(item: textField3, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField2, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
        let textField3Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField3, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
        let textField3Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField3, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
        contentView.addConstraints([textField3Top, textField3Leading, textField3Trailing])

        let textField4Top : NSLayoutConstraint = NSLayoutConstraint(item: textField4, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField3, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
        let textField4Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField4, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
        let textField4Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField4, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
        contentView.addConstraints([textField4Top, textField4Leading, textField4Trailing])

        let textField5Top : NSLayoutConstraint = NSLayoutConstraint(item: textField5, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField4, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
        let textField5Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField5, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
        let textField5Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField5, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
        contentView.addConstraints([textField5Top, textField5Leading, textField5Trailing])

        let textField6Top : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: textField5, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 100)
        let textField6Leading : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 40)
        let textField6Trailing : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: -40)
        let textField6Bottom : NSLayoutConstraint = NSLayoutConstraint(item: textField6, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.GreaterThanOrEqual, toItem: contentView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
        contentView.addConstraints([textField6Top, textField6Leading, textField6Trailing, textField6Bottom])
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()


        // Dispose of any resources that can be recreated.
    }


}

这是我用于文本字段的CustomTextField 类:

class CustomTextField: UITextField {
    override init(frame: CGRect) {
        super.init(frame: frame)

        backgroundColor = .whiteColor()

        // set text field height to 55pts
        let heightLC : NSLayoutConstraint = NSLayoutConstraint(item: self, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 55)
        addConstraint(heightLC)
    }

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

这是该应用当前的外观 (注意第 6 个文本字段没有显示,我无法向下滚动到它):

任何帮助将不胜感激:)

【问题讨论】:

  • 你检查过scrollView的contentSize属性吗?这是我首先想到的。我不确定它如何与约束交互,但它可能不会被隐式设置。
  • 是的,scrollView.contentSize 打印 (0.0, 0.0)。任何想法为什么它没有被隐式设置?
  • 什么都没有想到。你能用 UITableView 完成你想要实现的目标吗?否则,您必须计算大小并明确设置它。

标签: ios swift uiscrollview autolayout


【解决方案1】:

问题在于以下几行:

    let contentViewTopLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
    let contentViewLeadingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)
    let contentViewTrailingLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)
    let contentViewBottomLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)
    let contentViewWidthLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Width, multiplier: 1.0, constant: 0)
    let contentViewHeightLC : NSLayoutConstraint = NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Height, multiplier: 1.0, constant: 0)
    scrollView.addConstraints([contentViewTopLC,contentViewLeadingLC,contentViewTrailingLC,contentViewBottomLC,contentViewWidthLC,contentViewHeightLC])

你想要的根本不是让内容视图的大小滚动视图。这正是保持滚动视图不滚动的原因。您希望将内容视图的四个边缘固定到滚动视图的四个边缘。

这样,内容视图的内容将向外推到内容视图上,调整其大小。因此它将尝试变得比滚动视图更大。但它不能,因为您还将滚动视图的两侧固定到 超级视图。因此,内容视图的大小将成为滚动视图的边界大小 - 它的contentSize。当滚动视图的contentSize 大于滚动视图时,它将是可滚动的。

【讨论】:

  • 你说你在代码中找不到能做到这一切的例子。显然你没有读过我的书,因为这正是它所采用的方法。在我书中的这个例子中,你应该专注于“案例 3”——它用代码自动布局整个事情。 github.com/mattneub/Programming-iOS-Book-Examples/blob/master/…
  • 感谢您的回答,马特。所以基本上你说的只是删除 contentViewWidthLC 和 contentViewHeightLC 约束,并添加 4 个约束来将内容视图固定到滚动视图的边缘?我只是重申这个原因,这就是我尝试过的,但仍然没有运气。当我这样做时,我的屏幕上什么都没有显示
  • 看例子!它向您展示了使用内容视图时自动布局/无自动布局的所有四种组合。下载它。运行。复制它。
  • “你说只是删除”我没有说“只是删除”任何东西。所有这些限制都是错误的。内容视图必须固定到滚动视图的所有四个边缘。然后 内容必须在所有四个边上完全 被限制以推动向外 来决定内容大小。
  • 也许我只是不了解约束,但我认为 contentViewTopLCcontentViewLeadingLCcontentViewTrailingLCcontentViewBottomLC 将 contentView 固定到滚动视图的 4 个边缘。
猜你喜欢
  • 1970-01-01
  • 2016-12-15
  • 2013-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多