Swift - 如何将一堆视图放入scrollview中

时间:2018-06-17 12:59:40

标签: swift layout uiscrollview constraints uistackview

C urrently我有一个包含许多视图的自定义视图(返回UIStakView)(UILabel,UIImageView,...)。它显示精细 - 在高度充足的设备上。

(顺便说一句,这都是以编程方式完成的。。)

在小屏幕设备上,它只会显示整个视图的顶部。所以我的解决方案是将它放在UIScrollView中。 (这应该很简单 - 但它给了我很多悲伤。)

但这根本没有显示,我做错了什么/错过了什么?

以下部分代码:

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

    imageFrame.addSubview(prodImage)
    NSLayoutConstraint.activate([
        prodImage.topAnchor.constraint(equalTo: imageFrame.topAnchor),
        prodImage.trailingAnchor.constraint(equalTo: imageFrame.trailingAnchor),
        prodImage.leadingAnchor.constraint(equalTo: imageFrame.leadingAnchor),
        prodImage.bottomAnchor.constraint(equalTo: imageFrame.bottomAnchor),
        ])

    imageView.addSubview(imageFrame)
    NSLayoutConstraint.activate([
        imageFrame.topAnchor.constraint(equalTo: imageView.topAnchor),
        imageFrame.trailingAnchor.constraint(equalTo: imageView.trailingAnchor),
        imageFrame.leadingAnchor.constraint(equalTo: imageView.leadingAnchor),
        imageFrame.bottomAnchor.constraint(equalTo: imageView.bottomAnchor),
        ])

//更多观看次数......

    let stack = UIStackView(arrangedSubviews: [imageView, prodName, prodPrice])
    stack.axis = .vertical
    stack.spacing = (self.frame.height > 400) ? (self.frame.height > 800) ? 15 : 10 : 5
    stack.distribution = UIStackViewDistribution.fill

    self.addSubview(stack)
    NSLayoutConstraint.activate([
        stack.leadingAnchor.constraint(equalTo: self.leadingAnchor),
        stack.topAnchor.constraint(equalTo: self.topAnchor),
//      stack.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50),
        stack.widthAnchor.constraint(equalTo: self.widthAnchor),
        ])
}

要进行更改,我替换了底部的一节:

//  self.addSubview(stack)
//  NSLayoutConstraint.activate([
//      stack.leadingAnchor.constraint(equalTo: self.leadingAnchor),
//      stack.topAnchor.constraint(equalTo: self.topAnchor),
////        stack.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50),
//      stack.widthAnchor.constraint(equalTo: self.widthAnchor),
//      ])
    let scrollView = UIScrollView()
    //      scrollView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(stack)
    NSLayoutConstraint.activate([
        stack.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
        stack.topAnchor.constraint(equalTo: scrollView.topAnchor),
        stack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -50),
        stack.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
        ])

    self.addSubview(scrollView)
    NSLayoutConstraint.activate([
        scrollView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
        scrollView.topAnchor.constraint(equalTo: self.topAnchor),
        scrollView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -50),
        scrollView.widthAnchor.constraint(equalTo: self.widthAnchor),
        ])

正如您所看到的,我尝试禁用滚动视图的自动约束以使其适合其父级...所有尝试都失败。

如何使此滚动视图可见?

1 个答案:

答案 0 :(得分:0)

可能的错误:

  • 您正在将堆栈视图的前导/尾随设置为滚动视图。
  • 如果您打印框架,您可能会理解宽度为零

这是因为:

  • 堆栈视图的宽度无法根据滚动视图确定。
  • 滚动视图是一种特殊视图,因为它的内容可能比滚动视图大。
  • 所以你需要明确设置内容视图(堆栈视图' s)

可能的修复1:

而不是基于scrollViewview上设置它(假设将scrollView作为子视图添加到viewController的视图中)

    stack.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    stack.topAnchor.constraint(equalTo: view.topAnchor),

可能的修复2:

您可以明确设置堆栈视图的宽度锚

实施例

下面给出了一个如何使用滚动视图使用堆栈视图的简单示例。

你的想法是正确的。

  • 滚动视图具有堆栈视图
  • 堆栈视图有几个子视图

屏幕截图:

ScreenShot of the code

一般说明:

  • 滚动视图很特别,因为滚动视图的内容可以比滚动视图本身更宽更高(允许它滚动)
  • 因此,内容的宽度和高度不应与滚动视图相关联
  • 应设置内容的宽度和高度,而滚动视图没有任何可播放的部分

策略

  • 正如您所指出的,我喜欢使用滚动视图和内容视图
  • 将实际内容添加到堆栈视图中,让堆栈视图增长
  • 因此,只要正确设置了滚动视图的堆栈视图约束,就应该落实到位。

调试:

  • 始终在viewDidAppear中打印框架值以查看是否符合您的预期

示例代码:

class ViewController: UIViewController {

    let scrollView  = UIScrollView()
    let contentView = UIStackView()

    let redView     = UIView()
    let greenView   = UIView()
    let yellowView  = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        setupScrollView()
        setupContentView()
        setupRedView()
        setupGreenView()
        setupYellowView()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        print("scroll view  = \(scrollView.frame)")
        print("content view = \(contentView.frame)")
        print("red view     = \(redView.frame)")
        print("green view   = \(greenView.frame)")
        print("yellow view  = \(yellowView.frame)")
    }

    private func setupScrollView() {

        scrollView.backgroundColor = .darkGray

        view.addSubview(scrollView)

        scrollView.translatesAutoresizingMaskIntoConstraints = false

        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    }

    private func setupContentView() {

        contentView.axis            = .vertical
        contentView.distribution    = .fill
        contentView.alignment       = .fill

        scrollView.addSubview(contentView)

        contentView.translatesAutoresizingMaskIntoConstraints = false

        //Strategy is:
        //content view's leading / trailing anchors are set to view controller's view
        //content view's top / bottom anchors are set to scroll view

        contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        contentView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    }

    private func setupRedView() {

        redView.backgroundColor = .red

        redView.heightAnchor.constraint(equalToConstant: 400).isActive = true

        contentView.addArrangedSubview(redView)
    }

    private func setupGreenView() {

        greenView.backgroundColor = .green

        greenView.heightAnchor.constraint(equalToConstant: 400).isActive = true

        contentView.addArrangedSubview(greenView)
    }

    private func setupYellowView() {

        yellowView.backgroundColor = .yellow

        yellowView.heightAnchor.constraint(equalToConstant: 400).isActive = true

        contentView.addArrangedSubview(yellowView)
    }
}