在将视图添加到我的应用程序之前,我创建了一个小演示场来使其工作。
我有一个滚动视图,该视图将包含许多按钮来水平滚动。我知道这些按钮需要进入滚动视图内的容器视图,并且也已经创建了。我最初使用自动布局约束创建所有这些内容,但是现在尝试使用常量来确保内容视图大于滚动视图。但是,按钮仍然不会滚动…我错过了什么吗?滚动视图不适用于自动布局吗?
我也在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,内容将水平滚动。
containerView
scrollView
注意: 以scrollView这种方式配置时,请勿设置contentSize的scrollView。在contentSize将计算为你 自动布局 ,这将是相等的大小containerView。重要的是要确保containerView约束的大小完全指定的大小。
contentSize
这是我为了使其工作而进行的更改:
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的宽度。关键是for循环之后的最终约束,在该循环中viewDidLoad(),最后一个按钮的traceingAnchor(aka startPoint)连接到了containerViewTrailingAnchor。这样就完成了约束和纽扣链,将的前缘containerView与的后缘连接起来containerView。有了这个, 自动布局 能够计算的宽度containerView和建立contentSize的scrollView。
for
viewDidLoad()
startPoint
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