向视图添加约束,其topAnchor是具有动态高度的UIView的bottomAnchor,Swift,UIKit,Programmatic

问题描述 投票:0回答:2

我创建了一个 UIView,其中有按钮。我这样设置约束:

NSLayoutConstraint.activate([
    sampleView.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 20),
    sampleView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
    sampleView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
])

没有添加任何高度或底部锚点,因为我希望它的高度是动态的。 最初,sampleView 没有按钮,因此它不会出现在 UI 中。然后我在其中添加彼此垂直的按钮,效果很好。

我现在面临的问题是,在这个sampleView下面还有另一个视图(tempView)。最初我将 tempView 的 topAnchor 设置为sampleView 的bottomAnchor。 所以它最初就正确地放置在屏幕上。

当我在 SampleView 中添加按钮时,它会展开,但 tempView 不会。我尝试使用 view.layoutIfNeeded() 并使用sampleView的新高度设置topAnchor,但对我来说没有任何效果。

请帮我解决这个问题。

ios swift uiview uikit nslayoutconstraint
2个回答
0
投票

您必须做某事才能给

sampleView
一个高度

一种简单的方法是添加垂直

UIStackView
作为
sampleView
的子视图,将所有 4 个边约束为
sampleView
,然后添加按钮作为堆栈视图的排列子视图。

简单示例:

class ExampleVC: UIViewController {
    
    let topView = UIView()
    let sampleView = UIView()
    let tempView = UIView()
    
    // let's use a vertical stack view to hold the buttons inside sampleView
    let stackView = UIStackView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBackground
        
        [topView, sampleView, tempView].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(v)
        }
        
        topView.backgroundColor = .yellow
        sampleView.backgroundColor = .green
        tempView.backgroundColor = .cyan
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            
            topView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            topView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
            topView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0),
            topView.heightAnchor.constraint(equalToConstant: 100.0),
            
            sampleView.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 20.0),
            sampleView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
            sampleView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0),
            // sampleView has no Height constraint ...
            //  we're adding a stack view to it, and as we add buttons to the stack view
            //  it will control the Height
            
            tempView.topAnchor.constraint(equalTo: sampleView.bottomAnchor, constant: 20.0),
            tempView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
            tempView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0),
            tempView.heightAnchor.constraint(equalToConstant: 100.0),
            
        ])
        
        // stackView to hold the buttons
        stackView.axis = .vertical
        stackView.spacing = 8
        
        stackView.translatesAutoresizingMaskIntoConstraints = false
        sampleView.addSubview(stackView)
        
        NSLayoutConstraint.activate([
            
            // constrain all 4 sides of the stack view to sampleView
            stackView.topAnchor.constraint(equalTo: sampleView.topAnchor, constant: 0.0),
            stackView.leadingAnchor.constraint(equalTo: sampleView.leadingAnchor, constant: 0.0),
            stackView.trailingAnchor.constraint(equalTo: sampleView.trailingAnchor, constant: 0.0),
            stackView.bottomAnchor.constraint(equalTo: sampleView.bottomAnchor, constant: 0.0),
            
        ])
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let btnNumber = stackView.arrangedSubviews.count + 1
        let btn = UIButton()
        btn.backgroundColor = .red
        btn.setTitle("Button \(btnNumber)", for: [])
        stackView.addArrangedSubview(btn)
    }
    
}

开始时,因为我们没有向堆栈视图添加任何按钮,所以它看起来像这样:

点击任意位置即可添加按钮——这是第一次点击后我们得到的结果:

再点击几次后:


0
投票
class ViewController: UIViewController {

///Variable
var viewA: UIView!

///View lifecycle functions
override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    
    viewA = UIView()
    viewA.translatesAutoresizingMaskIntoConstraints = false
    viewA.backgroundColor = .red
    view.addSubview(viewA)
    
    let viewB = UIView()
    viewB.translatesAutoresizingMaskIntoConstraints = false
    viewB.backgroundColor = .green
    view.addSubview(viewB)
    
    
    
    NSLayoutConstraint.activate([
        viewA.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
        viewA.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
        viewA.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
        
        viewB.topAnchor.constraint(equalTo: viewA.bottomAnchor, constant: 20),
        viewB.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
        viewB.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
        viewB.heightAnchor.constraint(equalToConstant: 50),
        
        
    ])
    viewA.layoutIfNeeded()
    
    setupSubview()
}
override func viewDidLayoutSubviews() {
    view.layoutIfNeeded()
}
func setupSubview(){
    DispatchQueue.main.asyncAfter(deadline: .now() + 5 ) {
        let viewSub = UIView()
        viewSub.translatesAutoresizingMaskIntoConstraints = false
        viewSub.backgroundColor = .purple
        self.viewA.addSubview(viewSub)
        
        NSLayoutConstraint.activate([
           
            viewSub.topAnchor.constraint(equalTo: self.viewA.topAnchor, constant: 20),
            viewSub.leadingAnchor.constraint(equalTo: self.viewA.leadingAnchor, constant: 16),
            viewSub.trailingAnchor.constraint(equalTo: self.viewA.trailingAnchor, constant: -16),
            viewSub.heightAnchor.constraint(equalToConstant: 60),
            viewSub.bottomAnchor.constraint(equalTo: self.viewA.bottomAnchor)
          
        ])
        
        self.viewA.layoutIfNeeded()
        print(self.viewA.frame)
    }
}

}

© www.soinside.com 2019 - 2024. All rights reserved.