2016-05-14 85 views
12

我知道这个问题已被问了很多次,但这是一个我一直在苦苦挣扎的问题,我相信其他人也是如此,即使当前的答案和教程在那里。使用滚动视图和Autolayout Swift

当添加滚动视图我经过以下步骤:

  1. 添加滚动视图可以在视图控制器原始视图的一个子视图。钉住顶部,左侧,右侧和底部。确保“限制利润率”不受限制。

  2. 添加一个UIView作为滚动视图的子视图。 Pin顶部,左侧,右侧和底部限制。

  3. 在内容视图和视图控制器视图之间添加等宽度约束。

在我运行应用程序的时候,内容视图不会出现,滚动视图会占用整个屏幕。

  1. 接下来,我将内容添加到内容视图中,只包含4个UIViews来测试所有内容。我给每个UIView顶部,左侧和右侧的约束。最后一个UIView是一个底部约束。

不是在这个时候,当我运行应用时,内容视图和滚动视图每个占用大约一半的屏幕,我可以滚动内容视图。看下面的照片。

我跟着每一个教程,我可以找到并试图实现所有我找到的答案,但我似乎无法得到它的工作。如果有人遇到这个问题或知道解决方案,您的帮助将非常感谢!

绿色是内容的浏览和蓝色是滚动视图

enter image description here

滚动视图和子视图限制

enter image description here

+0

您可以加入约束问题截图?......还告诉滚动视图的大小和它的子视图 – sanman

+0

添加的约束截图。你是什​​么意思的大小?我正在使用纵向尺寸类中的所有iPhone,并填充视图。 – m1234

+0

我之前并不清楚...我想知道你为底部约束设置了什么值。将它设置为零。通过尺寸我的意思是x,y和高度,宽度。确保contentview的高度大于scrollview.for试验只创建高度为100和contentview的卷轴与高度400与一些按钮结束。您添加的约束是正确的,只需将底部一个设置为零。希望它有帮助:) – sanman

回答

44

我想通了这一点与其他的答案的帮助,但我不得不做出一些调整,以得到它的工作我想要的方式。以下是我采取的步骤:

  1. 将主视图的子视图添加为滚动视图。

  2. 选择滚动视图,取消选择“约束到利润”和引脚上,左,右,下,约束

  3. 添加一个UIView作为滚动视图的子视图。将此视图命名为“内容视图”

  4. 选择内容视图并固定顶部,左侧,右侧和底部约束。然后添加一个中心水平约束。

  5. 接下来从内容视图到主视图添加等宽和等高限制。

  6. 在内容视图中添加您需要的任何元素。针对刚刚添加的元素添加顶部,左侧,右侧和高度限制。

  7. 在内容视图中最底部的项目上钉住底部约束。选择此约束并更改为“大于或等于”。将常数改为20.

添加到内容视图内的项目的约束非常重要,特别是添加到最后一项的底部约束。它们有助于确定滚动视图的内容大小。如上所述添加底部约束将使视图在内容太大而无法放入屏幕时滚动,如果内容适合屏幕,则禁用滚动。

+4

金色。在我发现的任何教程中都没有讨论底部项目约束的重要性。他们都建议指定scrollView的contentSize。但大多数情况下,我们需要一个autoresizing scrollView取决于它的内容!谢谢。 –

+0

步骤1 - 4我一直在关注一段时间,但是我已经有更好的运气替换步骤5和7,其中包含以下内容: 除了水平中心约束之外,还在内容视图的容器约束中垂直添加一个中心。 在容器约束中的垂直中心的属性部分中,在“在构建时删除”下打上复选标记 使用这两种居中约束,界面构建器将允许您将对象放置在内容视图中,因为它应该如此。 – Padawan

+0

仍然遇到scrollView的“Y位置或高度的极限约束”。 – Meshach

0

的UIScrollView的类滚动通过改变原有的内容的界限。为了使此功能适用于自动布局,滚动视图中的顶部,左侧,底部和右侧边缘现在意味着其内容视图的边缘。

对滚动视图的子视图的约束必须导致要填充的大小,然后将其解释为滚动视图的内容大小。 (这不应与用于自动布局的intrinsicContentSize方法混淆)。要使用自动布局调整滚动视图的框架,约束必须是关于滚动视图的宽度和高度的显式,或者滚动视图的边缘必须是绑在其子树之外的视图上。

也看到了技术说明苹果写了关于这个问题: https://developer.apple.com/library/ios/technotes/tn2154/_index.html

2

我花了很多时间来算出这个和它很简单。这是解决方案。请按照以下步骤

  • 添加滚动型作为主视图
  • 引脚上,左,右,下,水平在容器中,垂直于容器的子视图。
  • 将容器视图添加为滚动视图的子视图
  • 在容器中水平放置顶部,左侧,右侧,底部,垂直放置在容器中。
  • 在具有所需限制的容器视图中添加子视图。
  • 相应地设置滚动视图的内容大小。

保持滚动:)

+0

谢谢,但是当我尝试这样它不会滚动 – m1234

+0

您是否设置了滚动视图的内容大小? –

+0

我只是按照你制定的步骤。我应该如何设置它? – m1234

2

我已在代码的简单观点,即应该是不言而喻的,并且可能帮助你。它概述了为使滚动视图正常工作所需的所有步骤。

如果有什么不清楚的地方,请随时发表评论。

import UIKit 

class TutorialView: UIView { 

    lazy var sv: UIScrollView = { 
     let object = UIScrollView() 

     object.backgroundColor = UIColor.whiteColor() 
     object.translatesAutoresizingMaskIntoConstraints = false 
     return object 
    }() 

    lazy var tutorialPageOne: UIView = { 
     let object = UIView(frame: UIScreen.mainScreen().bounds) 
     object.translatesAutoresizingMaskIntoConstraints = false 
     object.backgroundColor = UIColor.cyanColor() 

     return object 
    }() 

    lazy var tutorialPageTwo: UIView = { 
     let object = UIView(frame: UIScreen.mainScreen().bounds) 
     object.translatesAutoresizingMaskIntoConstraints = false 
     object.backgroundColor = UIColor.lightGrayColor() 

     return object 
    }() 

    lazy var tutorialPageThree: UIView = { 
     let object = UIView(frame: UIScreen.mainScreen().bounds) 
     object.translatesAutoresizingMaskIntoConstraints = false 
     object.backgroundColor = UIColor.redColor() 

     return object 
    }() 

    override init(frame: CGRect) { 
     super.init(frame: frame) 

     self.addSubview(self.sv) 
     self.sv.addSubview(self.tutorialPageOne) 
     self.sv.addSubview(self.tutorialPageTwo) 
     self.sv.addSubview(self.tutorialPageThree) 
    } 

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

    override func layoutSubviews() { 
     super.layoutSubviews() 

     let vc = nextResponder() as? UIViewController 
     let mainSreenWidth = UIScreen.mainScreen().bounds.size.width 
     let mainScreenHeight = UIScreen.mainScreen().bounds.size.height 

     NSLayoutConstraint.activateConstraints([ 
      self.sv.topAnchor.constraintEqualToAnchor(vc?.topLayoutGuide.bottomAnchor), 
      self.sv.leadingAnchor.constraintEqualToAnchor(self.leadingAnchor), 
      self.sv.bottomAnchor.constraintEqualToAnchor(vc?.bottomLayoutGuide.topAnchor), 
      self.sv.trailingAnchor.constraintEqualToAnchor(self.trailingAnchor) 
     ]) 

     NSLayoutConstraint.activateConstraints([ 
      self.tutorialPageOne.widthAnchor.constraintEqualToConstant(mainSreenWidth), 
      self.tutorialPageOne.heightAnchor.constraintEqualToConstant(mainScreenHeight), 
      self.tutorialPageOne.topAnchor.constraintEqualToAnchor(self.sv.topAnchor), 
      self.tutorialPageOne.leadingAnchor.constraintEqualToAnchor(self.sv.leadingAnchor), 
      self.tutorialPageOne.bottomAnchor.constraintEqualToAnchor(self.sv.bottomAnchor) 
     ]) 


     NSLayoutConstraint.activateConstraints([ 
      self.tutorialPageTwo.widthAnchor.constraintEqualToConstant(mainSreenWidth), 
      self.tutorialPageTwo.heightAnchor.constraintEqualToConstant(mainScreenHeight), 
      self.tutorialPageTwo.topAnchor.constraintEqualToAnchor(self.sv.topAnchor), 
      self.tutorialPageTwo.leadingAnchor.constraintEqualToAnchor(self.tutorialPageOne.trailingAnchor), 
      self.tutorialPageTwo.bottomAnchor.constraintEqualToAnchor(self.sv.bottomAnchor) 
     ]) 

     NSLayoutConstraint.activateConstraints([ 
      self.tutorialPageThree.widthAnchor.constraintEqualToConstant(mainSreenWidth), 
      self.tutorialPageThree.heightAnchor.constraintEqualToConstant(mainScreenHeight), 
      self.tutorialPageThree.topAnchor.constraintEqualToAnchor(self.sv.topAnchor), 
      self.tutorialPageThree.leadingAnchor.constraintEqualToAnchor(self.tutorialPageTwo.trailingAnchor), 
      self.tutorialPageThree.bottomAnchor.constraintEqualToAnchor(self.sv.bottomAnchor), 
      self.tutorialPageThree.trailingAnchor.constraintEqualToAnchor(self.sv.trailingAnchor) 
     ]) 

    } 
} 
+0

Tom,你的代码当然是自我解释的,特别是在Swift 3中。假设Tutorial.swift需要是'ViewController'的'SubView',这可能成为另一篇文章的接受答案,我的代码可以通过'autolayout '。如果你有兴趣在这里发布http://stackoverflow.com/questions/40996685/in-uiscrollview-uiview-displays-successive-frame-information-correctly-while-uil/41006889#41006889 – Greg

0

我知道如何滚动型内创建UI没有代码的最佳方式是:

  1. 您的滚动视图添加到的UIViewController与它和它的父视图之间的适当约束。
  2. 将“大括号视图”添加到滚动视图。
  3. “Brace view”应该隐藏,因为它不是最终用户界面的一部分。
  4. 使左,上,右包含“大括号视图”和UIScrollView之间。做高度限制。 (高度约束可以是任何数字)。使中心x对齐UIScrollView约束。

  5. 在“大括号视图”下面添加最终的UI。

  6. 在第一个最终用户界面视图和“大括号视图”之间添加顶部约束。
  7. 将所有最终UI视图与顶部或底部约束链接在一起。
  8. 添加适当的最终UI约束。
  9. 在最后一个最终UI视图和滚动视图之间添加底部约束。 (这个constraint.constant非常重要,因为它是你最终UI的一部分)。

下面是一个快速的github project示例。

enter image description here enter image description here

0

按@ M1234,但是你需要释放的高度相等,否则滚动不工作 - 我的方法是为这样的:

  1. 添加滚动视图作为主视图的副视点。

  2. 选择滚动视图,取消选择“约束到利润”和引脚上,左,右,下,约束

  3. 添加一个UIView作为滚动视图的子视图。将此视图命名为“内容视图”

  4. 选择内容视图并固定顶部,左侧,右侧和底部约束。然后添加一个中心水平约束。

  5. 接下来从内容视图到主视图添加等宽度约束。

  6. 在内容视图中添加您需要的任何元素。针对刚刚添加的元素添加顶部,左侧,右侧和高度限制。

  7. 在内容视图中最底部的项目上钉住底部约束。选择此约束并更改为“大于或等于”。将常数改为20.

2

给那些正在寻找示例UIScrollView和AutoLayout的人。我使用SnapKit,这是工作的Xcode 9,斯威夫特3

let scrollView = UIScrollView() 
    view.addSubview(scrollView) 
    scrollView.snp.makeConstraints { (make) in 
     make.edges.equalTo(view).inset(UIEdgeInsetsMake(0, 0, 0, 0)) 
     make.top.left.right.equalTo(view) 
    } 

    let view1 = UIView() 
    view1.backgroundColor = UIColor.red 
    scrollView.addSubview(view1) 
    view1.snp.makeConstraints { (make) in 
     make.top.equalTo(scrollView.snp.top).offset(0) 
     make.left.equalTo(scrollView.snp.left).offset(0) 
     make.width.equalTo(scrollView.snp.width) 
     make.height.equalTo(300) 
    } 

    let view2 = UIView() 
    view2.backgroundColor = UIColor.blue 
    scrollView.addSubview(view2) 
    view2.snp.makeConstraints { (make) in 
     make.top.equalTo(view1.snp.bottom) 
     make.left.equalTo(scrollView) 
     make.width.equalTo(scrollView) 
     make.height.equalTo(300) 
    } 

    let view3 = UIView() 
    view3.backgroundColor = UIColor.green 
    scrollView.addSubview(view3) 
    view3.snp.makeConstraints { (make) in 
     make.top.equalTo(view2.snp.bottom) 
     make.left.equalTo(scrollView) 
     make.width.equalTo(scrollView) 
     make.height.equalTo(100) 
     make.bottom.equalTo(scrollView.snp.bottom).offset(-20) 
    }