![](/img/trans.png)
[英]Swift: I'm not able to make autolayout constraints work for my UIScrollView
[英]My Swift 4 UIScrollView with autolayout constraints is not scrolling
在将视图添加到我的应用程序之前,我创建了一个小演示场来使其工作。
我有一个滚动视图,该视图将包含许多按钮来水平滚动。 我知道这些按钮需要进入滚动视图内的容器视图,并且也已经创建了。 我最初使用自动布局约束创建所有这些内容,但是现在尝试使用常量来确保内容视图大于滚动视图。 但是,按钮仍然无法滚动...我错过了什么吗? 滚动视图不适用于自动布局吗?
我也在iPad上以编程方式进行了所有这些操作,因此不幸的是,无法使用Interface Builder解决方案...
这是完整的代码:
import UIKit
import PlaygroundSupport
class FilterViewController: UIViewController {
var filterView: UIView!
var scrollView: UIScrollView!
var containerView: UIView!
override func loadView() {
filterView = UIView()
view = filterView
view.backgroundColor = #colorLiteral(red: 0.909803926944733, green: 0.47843137383461, blue: 0.643137276172638, alpha: 1.0)
scrollView = UIScrollView()
scrollView.backgroundColor = #colorLiteral(red: 0.474509805440903, green: 0.839215695858002, blue: 0.976470589637756, alpha: 1.0)
view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.topAnchor.constraint(equalTo:view.topAnchor, constant:40).isActive = true
scrollView.leadingAnchor.constraint(equalTo:view.leadingAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo:view.widthAnchor).isActive = true
scrollView.heightAnchor.constraint(equalToConstant: 200).isActive = true
scrollView.isScrollEnabled = true
containerView = UIView()
containerView.backgroundColor = #colorLiteral(red: 0.176470592617989, green: 0.498039215803146, blue: 0.756862759590149, alpha: 1.0)
scrollView.addSubview(containerView)
containerView.frame = CGRect(x: 0, y: 0, width: 1080, height: 200)
}
class Buttons{
let button = UIButton()
init (titleText : String){
button.backgroundColor = #colorLiteral(red: 0.976470589637756, green: 0.850980401039124, blue: 0.549019634723663, alpha: 1.0)
button.setTitle(titleText, for: .normal)
button.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
}
}
override func viewDidLoad() {
super.viewDidLoad()
let b1 = Buttons(titleText: "one")
let b2 = Buttons(titleText: "two")
let b3 = Buttons(titleText: "three")
let b4 = Buttons(titleText: "four")
let b5 = Buttons(titleText: "five")
let buttonArray = [b1,b2,b3,b4,b5]
var startPoint : CGFloat = 0.0
for btn in buttonArray {
let theBtn = btn.button
containerView.addSubview(theBtn)
theBtn.frame = CGRect(x: startPoint, y: 0, width: 200, height: 200)
startPoint += 220
}
}
}
let filterViewController = FilterViewController()
PlaygroundPage.current.liveView = filterViewController
谢谢vacawama! 这是具有所有自动布局约束的完整的(正在运行的)迷你项目:
import UIKit
import PlaygroundSupport
class FilterViewController: UIViewController {
var filterView: UIView!
var scrollView: UIScrollView!
var containerView: UIView!
override func loadView() {
filterView = UIView()
view = filterView
view.backgroundColor = #colorLiteral(red: 0.909803926944733, green: 0.47843137383461, blue: 0.643137276172638, alpha: 1.0)
scrollView = UIScrollView()
scrollView.backgroundColor = #colorLiteral(red: 0.474509805440903, green: 0.839215695858002, blue: 0.976470589637756, alpha: 1.0)
view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.topAnchor.constraint(equalTo:view.topAnchor, constant:40).isActive = true
scrollView.leadingAnchor.constraint(equalTo:view.leadingAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo:view.widthAnchor).isActive = true
scrollView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.25).isActive = true
scrollView.isScrollEnabled = true
containerView = UIView()
containerView.backgroundColor = #colorLiteral(red: 0.176470592617989, green: 0.498039215803146, blue: 0.756862759590149, alpha: 1.0)
scrollView.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.topAnchor.constraint(equalTo:scrollView.topAnchor).isActive = true
containerView.leadingAnchor.constraint(equalTo:scrollView.leadingAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo:scrollView.trailingAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo:scrollView.bottomAnchor).isActive = true
containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
}
class Buttons{
let button = UIButton()
init (titleText : String){
button.backgroundColor = #colorLiteral(red: 0.976470589637756, green: 0.850980401039124, blue: 0.549019634723663, alpha: 1.0)
button.setTitle(titleText, for: .normal)
//button.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
}
}
override func viewDidLoad() {
super.viewDidLoad()
let b1 = Buttons(titleText: "one")
let b2 = Buttons(titleText: "two")
let b3 = Buttons(titleText: "three")
let b4 = Buttons(titleText: "four")
let b5 = Buttons(titleText: "five")
let buttonArray = [b1,b2,b3,b4,b5]
var startPoint = containerView.leadingAnchor
for btn in buttonArray {
let theBtn = btn.button
containerView.addSubview(theBtn)
theBtn.translatesAutoresizingMaskIntoConstraints = false
theBtn.leadingAnchor.constraint(equalTo:startPoint, constant:20).isActive = true
theBtn.topAnchor.constraint(equalTo:containerView.topAnchor).isActive = true
theBtn.bottomAnchor.constraint(equalTo:containerView.bottomAnchor).isActive = true
theBtn.widthAnchor.constraint(equalTo: theBtn.heightAnchor).isActive = true
startPoint = theBtn.trailingAnchor
containerView.widthAnchor.constraint(equalTo: theBtn.widthAnchor, multiplier:CGFloat(buttonArray.count), constant: CGFloat(buttonArray.count * 20)).isActive = true
}
}
}
let filterViewController = FilterViewController()
PlaygroundPage.current.liveView = filterViewController
您可以使用“ 自动布局”来执行此操作。 秘诀是将containerView
的边缘限制为scrollView
的边缘。 这不是很直观,但是约束containerView
的边缘并没有设置大小,只是确保了scrollView
的内容大小会随着containerView
增长而增长。 通过将containerView
的宽度约束设置为一个常量,该常量的数量大于scrollView
的宽度,则内容将水平滚动。
注意:当以这种方式配置scrollView
,不要设置scrollView
的contentSize
。 contentSize
将通过“ 自动布局”为您计算,它等于containerView
的大小。 确保约束完全指定containerView
的大小很重要。
这是我为了使其工作而进行的更改:
containerView = UIView()
containerView.backgroundColor = #colorLiteral(red: 0.176470592617989, green: 0.498039215803146, blue: 0.756862759590149, alpha: 1.0)
scrollView.addSubview(containerView)
//containerView.frame = CGRect(x: 0, y: 0, width: 1080, height: 200)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.topAnchor.constraint(equalTo:scrollView.topAnchor).isActive = true
containerView.leadingAnchor.constraint(equalTo:scrollView.leadingAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo:scrollView.trailingAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo:scrollView.bottomAnchor).isActive = true
containerView.heightAnchor.constraint(equalToConstant: 200).isActive = true
containerView.widthAnchor.constraint(equalToConstant: 1080).isActive = true
为什么我的内容没有滚动?
为了使其滚动, containerView
必须大于scrollView
。 您的错误是您已设置了约束,以使containerView
的宽度和高度与scrollView
宽度和高度相同,这就是为什么您的内容不滚动的原因。
如果要水平滚动, containerView
的宽度必须大于scrollView
的宽度。 您可以通过以下两种方式之一执行此操作:
为containerView
指定一个显式的恒定宽度,该宽度大于scrollView
的宽度。
要么
从左到右链接containerView
的子视图,其中最左边containerView
在containerView
前沿。 完全指定子视图的宽度,并在子视图之间放置距离约束。 最右边的子视图必须与containerView
的后沿有一个偏移量。 通过这样做,“ 自动布局”可以计算containerView
的宽度并设置scrollView
的contentSize
。
迷你项目:更新
这是迷你项目的一个版本,它使用一连串的约束视图来定义containerView
的宽度。 关键是viewDidLoad()
for
循环之后的最终约束,该约束将最后一个按钮的traceingAnchor(又名startPoint
)连接到containerView
的TrailingAnchor。 这样就完成约束上并且其连接的前缘按钮的链containerView
用的后缘containerView
。 这样,“ 自动布局”便可以计算containerView
的宽度并建立scrollView
的contentSize
。
import UIKit
import PlaygroundSupport
class FilterViewController: UIViewController {
var filterView: UIView!
var scrollView: UIScrollView!
var containerView: UIView!
override func loadView() {
filterView = UIView()
view = filterView
view.backgroundColor = #colorLiteral(red: 0.909803926944733, green: 0.47843137383461, blue: 0.643137276172638, alpha: 1.0)
scrollView = UIScrollView()
scrollView.backgroundColor = #colorLiteral(red: 0.474509805440903, green: 0.839215695858002, blue: 0.976470589637756, alpha: 1.0)
view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 40).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.25).isActive = true
scrollView.isScrollEnabled = true
containerView = UIView()
containerView.backgroundColor = #colorLiteral(red: 0.176470592617989, green: 0.498039215803146, blue: 0.756862759590149, alpha: 1.0)
scrollView.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
// This is key: connect all four edges of the containerView to
// to the edges of the scrollView
containerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
containerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
// Making containerView and scrollView the same height means the
// content will not scroll vertically
containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
}
class Buttons {
let button = UIButton()
init(titleText: String) {
button.backgroundColor = #colorLiteral(red: 0.976470589637756, green: 0.850980401039124, blue: 0.549019634723663, alpha: 1.0)
button.setTitle(titleText, for: .normal)
}
}
override func viewDidLoad() {
super.viewDidLoad()
let b1 = Buttons(titleText: "one")
let b2 = Buttons(titleText: "two")
let b3 = Buttons(titleText: "three")
let b4 = Buttons(titleText: "four")
let b5 = Buttons(titleText: "five")
let buttonArray = [b1, b2, b3, b4, b5]
var startPoint = containerView.leadingAnchor
for btn in buttonArray {
let theBtn = btn.button
containerView.addSubview(theBtn)
theBtn.translatesAutoresizingMaskIntoConstraints = false
theBtn.leadingAnchor.constraint(equalTo: startPoint, constant: 20).isActive = true
theBtn.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
theBtn.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
theBtn.widthAnchor.constraint(equalTo: theBtn.heightAnchor).isActive = true
startPoint = theBtn.trailingAnchor
}
// Complete the chain of constraints
containerView.trailingAnchor.constraint(equalTo: startPoint, constant: 20).isActive = true
}
}
let filterViewController = FilterViewController()
PlaygroundPage.current.liveView = filterViewController
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.