ios - 以编程方式在两个 subview 之间创建约束

标签 ios swift uiscrollview autolayout

我在 ScrollView 中有一个内容 View 以及其他一些 View , ScrollView 的高度会根据内容 View 的高度而变化,内容 View 的高度由其 subview 的高度决定。

我正在以编程方式向内容 View 添加两个 subview 。

childView1 = CustomView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 200))

childView2 = CustomView(frame: CGRect(x: 0, y: 210, width: self.view.frame.width, height: 200))

contentView.addSubview(childView1)
contentView.addSubview(childView2)

// childView1 top should be equal to contentView top           
let topConstraint = NSLayoutConstraint(item: childView1, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .top, multiplier: 1, constant: 0)

// childView2 bottom should be equal to contentView bottom                       
let bottomConstraint = NSLayoutConstraint(item: childView2, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottom, multiplier: 1, constant: 0)

// childView1 leading should be equal to contentView leading 

let leadingConstraint1 = NSLayoutConstraint(item: childView1, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 0)

// childView1 trailing should be equal to contentView trailing  

let trailingConstraint1 = NSLayoutConstraint(item: contentView1, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: 0)

// childView2 leading should be equal to contentView leading                       

let leadingConstraint2 = NSLayoutConstraint(item: childView2, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 0)

// childView2 trailing should be equal to contentView trailing  

let trailingConstraint2 = NSLayoutConstraint(item: childView2, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: 0)

// Vertical Space between two child views is 10             
let constraintTwoSubViews = NSLayoutConstraint(item: childView1, attribute: .bottom, relatedBy: .equal, toItem: childView2, attribute: .top, multiplier: 1, constant: 10)


contentView.addConstraints([topConstraint , bottomConstraint , leadingConstraint1,trailingConstraint1 , leadingConstraint2 , trailingConstraint2 , constraintTwoSubViews])

问题是 contentView 高度没有按照 subview 增长。 因此,我的滚动浏览量没有增长。

  1. 当我添加第二个 subview 时,我不想指定 y = 210 ,我希望它的位置通过空间约束来计算 两个 subview ,这可能吗?

  2. 如何使内容 View 高度根据其 subview 增长?

最佳答案

当我需要一个可 ScrollView 时我会做什么:

  1. 我将 scrollView 添加到层次结构中并使用自动布局对其进行适当布局,例如,如果它应该覆盖 的整个 view > View Controller :

    scrollView.translatesAutoresizingMaskIntoConstraints = false
    
    NSLayoutConstraint.activate([
        scrollView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
        scrollView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
        scrollView.topAnchor.constraint(equalTo: self.view.topAnchor),
        scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
    ])
    
  2. 然后你需要在 scrollView 中添加一个 contentView 并为其提供适当的布局约束,所以如果你想要垂直滚动 scrollView 在我上面开始的示例中,您需要遵循自动布局约束:

    contentView.translatesAutoresizingMaskIntoConstraints = false
    
    NSLayoutConstraint.activate([
        // horizontal anchors of contentView are constrained to scrollView superview
        // to prevent it from scrolling horizontally
        contentView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
        contentView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
        // but vertical anchors of contentView are constrained to
        // scrollView to allow scrolling
        contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
        contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
    ])
    

    请注意,我将 contentViewleftAnchorrightAnchor 约束到 self.view 而不是到 scrollView 使其具有固定宽度。但是,顶部和底部 anchor 被限制在 ScrollView 中,因此当 contentView 需要更多空间时,它们会展开并可滚动。

  3. 现在您向 contentView 添加您想要的所有内容,并使用自动布局对其进行布局,就像 contentView 是一个具有无限高度的 View 一样- scrollView 将负责通过滚动呈现它的整体。在你的情况下,我认为你可以使用 UIStackView 来布置这两个 View 。但是,CustomView 的框架将使用自动布局进行计算,因此我认为您不能直接依赖于设置框架 - 因此我也使用约束来设置它们的高度(宽度将被堆栈 View ):

    let stack = UIStackView()
    stack.spacing = 10
    stack.distribution = .fill
    stack.alignment = .fill
    stack.axis = .vertical
    
    contentView.addSubview(stack)
    stack.addArrangedSubview(childView1)
    stack.addArrangedSubview(childView2)
    
    childView1.translatesAutoresizingMasks = false
    childView2.translatesAutoresizingMasks = false
    
    NSLayoutConstraint.activate([
        contentView.topAnchor.constraint(equalTo: stack.topAnchor),
        contentView.leadingAnchor.constraint(equalTo: stack.leadingAnchor),
        contentView.trailingAnchor.constraint(equalTo: stack.trailingAnchor),
        contentView.bottomAnchor.constraint(equalTo: stack.bottomAnchor),
    
        // setting their heights using constraints
        childView1.heightAnchor.constraint(equalToConstant: 200),
        childView2.heightAnchor.constraint(equalToConstant: 200),
        ])
    

关于ios - 以编程方式在两个 subview 之间创建约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48279485/

相关文章:

ios - 如何快速正确激活约束

ios - UIScrollView 定点缩放,关闭捏合/捏合

ios - UIScrollView 不能出现

ios - UItableViewCell 内 UIScrollview 中的 UIButton 处理带有数据的事件

ios - 使用 PushKit 实现静默通知后 Apple 拒绝

iphone - 是否有包含 Core Plot 的示例项目?

swift - 在特定情况下不调用 deinit

ios - 将 UIPanGestureRecognizer 中的 CGPoint 从 .began 分配到 .changed

ios - 如何阻止从 super View 到 subview 的手势?

ios - 在 Swift QueryClosure 中将数组添加到数组