如何在 Swift 4 中使用锚点以编程方式向 UIScrolllView 添加视图

How to add views to the UIScrolllView programmatically using anchors in Swift 4

提问人:Tigran 提问时间:8/19/2018 最后编辑:Rakesha ShastriTigran 更新时间:9/27/2018 访问量:1091

问:

我在使用UIScrollView时遇到了一些问题。尝试添加可滚动适用于某些滑块,但没有任何效果。我认为这是因为我使用锚点进行布局。请向我解释,我做错了什么。最终,我需要为iPhone SE版本提供一个可滚动的区域,用户可以使用滑块。

iPhone X and iPhone SE

这是我的代码,我在其中创建滚动视图并在其上添加所有滑块,并放置与滚动视图相关的锚点。

    //MARK: Scroll View
    scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 812))
    scrollView.backgroundColor = .gray
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(scrollView)
    scrollView.topAnchor.constraint(equalTo: collectionView.bottomAnchor, constant: 0).isActive = true
    scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
    scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
    scrollView.contentSize = CGSize(width: view.bounds.width, height: 812)

    //MARK: Brightness Label
    brightnessLabel = UILabel()
    brightnessLabel.text = "Brightness"
    brightnessLabel.font = UIFont(name: "Avenir", size: 14)
    brightnessLabel.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(brightnessLabel)
    brightnessLabel.topAnchor.constraint(equalTo: collectionView.bottomAnchor, constant: 10).isActive = true
    brightnessLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: view.bounds.width / -2).isActive = true
    brightnessLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
    brightnessLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MARK: Brightness Slider
    brightnessSlider = UISlider()
    brightnessSlider.setThumbImage(UIImage(named: "sliderThumb"), for: .normal)
    brightnessSlider.tintColor = .black
    brightnessSlider.minimumValue = 0
    brightnessSlider.maximumValue = 100
    brightnessSlider.translatesAutoresizingMaskIntoConstraints = false
    brightnessSlider.setValue(50, animated: true)
    scrollView.addSubview(brightnessSlider)
    brightnessSlider.topAnchor.constraint(equalTo: brightnessLabel.bottomAnchor, constant: 5).isActive = true
    brightnessSlider.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
    brightnessSlider.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
    brightnessSlider.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MArk: Brightness Value Label
    brightnessValueLabel = UILabel()
    brightnessValueLabel.text = "50"
    brightnessValueLabel.font = UIFont(name: "Avenir", size: 14)
    brightnessValueLabel.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(brightnessValueLabel)
    brightnessValueLabel.topAnchor.constraint(equalTo: collectionView.bottomAnchor, constant: 10).isActive = true
    brightnessValueLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
    brightnessValueLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant:  view.bounds.width - 30).isActive = true
    brightnessValueLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MARK: Contrast Label
    contrastLabel = UILabel()
    contrastLabel.text = "Contrast"
    contrastLabel.font = UIFont(name: "Avenir", size: 14)
    contrastLabel.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(contrastLabel)
    contrastLabel.topAnchor.constraint(equalTo: brightnessSlider.bottomAnchor, constant: 10).isActive = true
    contrastLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: view.bounds.width / -2).isActive = true
    contrastLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
    contrastLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MARK: Contrast Slider
    contrastSlider = UISlider()
    contrastSlider.setThumbImage(UIImage(named: "sliderThumb"), for: .normal)
    contrastSlider.tintColor = .black
    contrastSlider.minimumValue = 0
    contrastSlider.maximumValue = 100
    contrastSlider.translatesAutoresizingMaskIntoConstraints = false
    contrastSlider.setValue(50, animated: true)
    scrollView.addSubview(contrastSlider)
    contrastSlider.topAnchor.constraint(equalTo: contrastLabel.bottomAnchor, constant: 5).isActive = true
    contrastSlider.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
    contrastSlider.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
    contrastSlider.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MArk: Contrast Value Label
    contrastValueLabel = UILabel()
    contrastValueLabel.text = "50"
    contrastValueLabel.font = UIFont(name: "Avenir", size: 14)
    contrastValueLabel.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(contrastValueLabel)
    contrastValueLabel.topAnchor.constraint(equalTo: brightnessSlider.bottomAnchor, constant: 10).isActive = true
    contrastValueLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
    contrastValueLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant:  view.bounds.width - 30).isActive = true
    contrastValueLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MARK: Saturation Label
    saturationLabel = UILabel()
    saturationLabel.text = "Saturation"
    saturationLabel.font = UIFont(name: "Avenir", size: 14)
    saturationLabel.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(saturationLabel)
    saturationLabel.topAnchor.constraint(equalTo: contrastSlider.bottomAnchor, constant: 10).isActive = true
    saturationLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: view.bounds.width / -2).isActive = true
    saturationLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
    saturationLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MARK: Saturation Slider
    saturationSlider = UISlider()
    saturationSlider.setThumbImage(UIImage(named: "sliderThumb"), for: .normal)
    saturationSlider.tintColor = .black
    saturationSlider.minimumValue = 0
    saturationSlider.maximumValue = 100
    saturationSlider.translatesAutoresizingMaskIntoConstraints = false
    saturationSlider.setValue(50, animated: true)
    scrollView.addSubview(saturationSlider)
    saturationSlider.topAnchor.constraint(equalTo: saturationLabel.bottomAnchor, constant: 5).isActive = true
    saturationSlider.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
    saturationSlider.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
    saturationSlider.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MArk: Saturation Value Label
    saturationValueLabel = UILabel()
    saturationValueLabel.text = "50"
    saturationValueLabel.font = UIFont(name: "Avenir", size: 14)
    saturationValueLabel.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(saturationValueLabel)
    saturationValueLabel.topAnchor.constraint(equalTo: contrastSlider.bottomAnchor, constant: 10).isActive = true
    saturationValueLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
    saturationValueLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant:  view.bounds.width - 30).isActive = true
    saturationValueLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MARK: Noise Label
    noiseLabel = UILabel()
    noiseLabel.text = "Noise"
    noiseLabel.font = UIFont(name: "Avenir", size: 14)
    noiseLabel.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(noiseLabel)
    noiseLabel.topAnchor.constraint(equalTo: saturationSlider.bottomAnchor, constant: 10).isActive = true
    noiseLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: view.bounds.width / -2).isActive = true
    noiseLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
    noiseLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MARK: Noise Slider
    noiseSlider = UISlider()
    noiseSlider.setThumbImage(UIImage(named: "sliderThumb"), for: .normal)
    noiseSlider.tintColor = .black
    noiseSlider.minimumValue = 0
    noiseSlider.maximumValue = 100
    noiseSlider.translatesAutoresizingMaskIntoConstraints = false
    noiseSlider.setValue(50, animated: true)
    scrollView.addSubview(noiseSlider)
    noiseSlider.topAnchor.constraint(equalTo: noiseLabel.bottomAnchor, constant: 5).isActive = true
    noiseSlider.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
    noiseSlider.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
    noiseSlider.heightAnchor.constraint(equalToConstant: 25).isActive = true

    //MArk: Noise Value Label
    noiseValueLabel = UILabel()
    noiseValueLabel.text = "50"
    noiseValueLabel.font = UIFont(name: "Avenir", size: 14)
    noiseValueLabel.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(noiseValueLabel)
    noiseValueLabel.topAnchor.constraint(equalTo: saturationSlider.bottomAnchor, constant: 10).isActive = true
    noiseValueLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
    noiseValueLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant:  view.bounds.width - 30).isActive = true
    noiseValueLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true

如果有人想知道,这是我的视图层次结构,我需要在滚动视图上的所有项目实际上都在滚动视图上。我在滚动视图中添加了灰色以使其可见。

enter image description here

iOS iPhone Swift UIscrollView 自动布局

评论

0赞 mfaani 8/19/2018
我强烈建议您阅读此答案及其评论。另外需要注意的是:当您使用自动布局时,您不应该设置 contentSize。scrollView 将自行调整大小
0赞 KSigWyatt 8/19/2018
我还建议将内容粘贴在图像下方,在堆栈视图控制器中,如果您还没有这样做的话。这可能也会对你有很大帮助。他们非常乐于助人。
1赞 mfaani 8/19/2018
此外,如果事情不起作用,那么我会首先从较少数量的子视图开始,然后在我让事情正常工作后,它会添加更多。太多的子视图会让你感到困惑

答:

1赞 Rakesha Shastri 8/19/2018 #1

当您使用自动布局时,您不需要指定 contentSize,它将从子视图中推断出来。条件是:

  • topmostView.topAnchor应附于scrollView.topAnchor
  • bottommostView.bottomAnchor应附于scrollView.bottomAnchor
  • 的前导和尾随应附加到任何具有宽度的视图。scrollView

我在你的代码中看到了一些问题。

  • 您似乎已将标签的前导和尾随附加到 scrollView,这不是您大多数时候想要执行的操作,因为 scrollView 宽度仅与标签的宽度一样大。

  • 您似乎还在多个位置附加了 scrollView 前导和尾随,这将计算导致冲突的不同前导和尾随约束。(我很确定,如果你检查你的日志,它会显示一些约束中断)

  • 您尚未将 内部的最上视图和最下视图的顶部或底部附加到 的顶部和底部。scrollViewscrollView

Apple 建议在使用 时,有一个虚拟视图 (contentView),它将固定到顶部、前导、尾随、底部,并具有指定的宽度。该视图的高度将根据您添加到该视图的视图动态计算。将最顶视图的顶部附加到 的顶部和最底部视图的底部附加到 的底部的概念相同。UIScrollViewscrollViewcontentViewcontentView

您可以查看我的 github 存储库,其中有一个简约的示例,它解释了 autolayout。UIScrollView

评论

0赞 Tigran 8/20/2018
我检查了所有内容,发现我没有在滚动视图的底部附加任何内容,只需添加一行,它就开始滚动。非常感谢。
0赞 Rakesha Shastri 8/20/2018
@Tigran是的,但是如果您检查日志,很多约束都会被破坏。请再次检查您的约束并解决冲突。它可能会滚动,但使约束中断不是好的做法。
0赞 Tigran 8/20/2018
该日志在哪里?你是说调试控制台?我没有任何类型的日志......一切都很好......
0赞 Rakesha Shastri 8/20/2018
@Tigran 哦,那么标签可能已经拉伸以适合滑块宽度或其他东西。好。如果您的调试控制台没有显示冲突,那么您就可以开始了!:D