xcode 如何在swift中以编程方式在不同情况下多次约束视图?

kgqe7b3p  于 2023-05-01  发布在  Swift
关注(0)|答案(2)|浏览(140)

我有一些标签作为一个按钮,每一个过滤我的表视图内容。在我的一个标签中,我需要将表视图移到底部一点。因为我必须向用户显示另一个视图,表视图必须在下面。
我有约束所有我的视图中没有加载方法第一,我应该约束我的tableView在标签侦听器再次。
下面是第一个约束代码

override func setupViews() {
    super.setupViews()

    view.addSubview(header)
    view.addSubview(serachOptionView)
    view.addSubview(tableView)
    header.addSubview(mytitle)
    view.addSubview(serachBarView)

    serachBarView.addSubview(serachInCityLabel)
    serachBarView.addSubview(serachInCountryLabel)
    serachBarView.addSubview(serachInTransitLabel)
    serachBarView.addSubview(advanceSearch)
    serachBarView.addSubview(columnLabelLeft)
    serachBarView.addSubview(columnLabelRight)



    //TO - DO header

    header.translatesAutoresizingMaskIntoConstraints=false
    header.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive=true
    header.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive=true
    header.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive=true
    header.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.17).isActive=true
    header.backgroundColor =  UIColor.init(patternImage: UIImage(named: "test.png")!)



    // MARK -- serachBarView

    serachBarView.translatesAutoresizingMaskIntoConstraints=false
    serachBarView.trailingAnchor.constraint(equalTo: header.trailingAnchor, constant: -3).isActive=true
    serachBarView.leadingAnchor.constraint(equalTo: header.leadingAnchor, constant: 3).isActive=true
    serachBarView.bottomAnchor.constraint(equalTo: header.bottomAnchor, constant: -1).isActive=true
    serachBarView.heightAnchor.constraint(equalTo: header.heightAnchor, multiplier: 0.27).isActive=true


    // MARK -- INCity

    serachInCityLabel.translatesAutoresizingMaskIntoConstraints=false
    serachInCityLabel.trailingAnchor.constraint(equalTo: serachBarView.trailingAnchor, constant: -5).isActive=true
    serachInCityLabel.topAnchor.constraint(equalTo: serachBarView.topAnchor, constant: 1).isActive=true
    serachInCityLabel.bottomAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: -1).isActive=true
    serachInCityLabel.widthAnchor.constraint(equalTo: serachBarView.widthAnchor, multiplier: 0.23).isActive=true

    // MARK -- columnLabelRight

    columnLabelRight.translatesAutoresizingMaskIntoConstraints=false
    columnLabelRight.trailingAnchor.constraint(equalTo: serachInCityLabel.leadingAnchor, constant: 0).isActive=true
    columnLabelRight.topAnchor.constraint(equalTo: serachInCityLabel.topAnchor, constant: 4).isActive=true
    columnLabelRight.bottomAnchor.constraint(equalTo: serachInCityLabel.bottomAnchor, constant: -4).isActive=true
    columnLabelRight.widthAnchor.constraint(equalToConstant: 1.5).isActive=true


    // MARK -- INCountry

    serachInCountryLabel.translatesAutoresizingMaskIntoConstraints=false
    serachInCountryLabel.trailingAnchor.constraint(equalTo: columnLabelRight.leadingAnchor, constant: 0).isActive=true
    serachInCountryLabel.topAnchor.constraint(equalTo: serachBarView.topAnchor, constant: 1).isActive=true
    serachInCountryLabel.bottomAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: -1).isActive=true
    serachInCountryLabel.widthAnchor.constraint(equalTo: serachBarView.widthAnchor, multiplier: 0.24).isActive=true

    // MARK -- columnLabelRight

    columnLabelLeft.translatesAutoresizingMaskIntoConstraints=false
    columnLabelLeft.trailingAnchor.constraint(equalTo: serachInCountryLabel.leadingAnchor, constant: 0).isActive=true
    columnLabelLeft.topAnchor.constraint(equalTo: serachInCountryLabel.topAnchor, constant: 4).isActive=true
    columnLabelLeft.bottomAnchor.constraint(equalTo: serachInCountryLabel.bottomAnchor, constant: -4).isActive=true
    columnLabelLeft.widthAnchor.constraint(equalToConstant: 1.5).isActive=true

    // MARK -- INTranis

    serachInTransitLabel.translatesAutoresizingMaskIntoConstraints=false
    serachInTransitLabel.trailingAnchor.constraint(equalTo: serachInCountryLabel.leadingAnchor, constant: 0).isActive=true
    serachInTransitLabel.topAnchor.constraint(equalTo: serachBarView.topAnchor, constant: 1).isActive=true
    serachInTransitLabel.bottomAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: -1).isActive=true
    serachInTransitLabel.widthAnchor.constraint(equalTo: serachBarView.widthAnchor, multiplier: 0.24).isActive=true

    // MARK -- advance search

    advanceSearch.translatesAutoresizingMaskIntoConstraints=false
    advanceSearch.trailingAnchor.constraint(equalTo: serachInTransitLabel.leadingAnchor, constant: 0).isActive=true
    advanceSearch.topAnchor.constraint(equalTo: serachBarView.topAnchor, constant: 1).isActive=true
    advanceSearch.bottomAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: -1).isActive=true
    advanceSearch.widthAnchor.constraint(equalTo: serachBarView.widthAnchor, multiplier: 0.24).isActive=true

    // MARK -- tableView

    tableView.translatesAutoresizingMaskIntoConstraints=false
    tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive=true

    tableView.topAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: 0).isActive=true
    tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive=true
    tableView.delegate=self
    tableView.dataSource=self
    tableView.register(specialGoodCell.self, forCellReuseIdentifier: "myCell")

}

and move below my table查看这里:

@objc func labelAction(){

      // MARK -- tableView

        tableView.translatesAutoresizingMaskIntoConstraints=false
        tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive=true

        tableView.topAnchor.constraint(equalTo: mypopUpView.bottomAnchor, constant: 0).isActive=true
        tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive=true
        tableView.delegate=self
        tableView.dataSource=self
        tableView.register(specialGoodCell.self, forCellReuseIdentifier: "myCell")

}

结果就是没有动静和警告
能够同时满足约束。

Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x28276f750 UIView:0x13fd45270.bottom == UIView:0x13fd4b2f0.bottom - 1   (active)>",
    "<NSLayoutConstraint:0x28276f610 V:[UIView:0x13fd45270]-(0)-[UITableView:0x1400a0000]   (active)>",
    "<NSLayoutConstraint:0x28276f2a0 V:[UIView:0x13fd4b2f0]-(40)-[UIView:0x13fd18a40]   (active)>",
    "<NSLayoutConstraint:0x28276f8e0 UIView:0x13fd18a40.height == 0.16*UIView:0x13fe428e0.height   (active)>",
    "<NSLayoutConstraint:0x28276a990 V:[UIView:0x13fd18a40]-(0)-[UITableView:0x1400a0000]   (active)>",
    "<NSLayoutConstraint:0x28276cb40 'UIView-Encapsulated-Layout-Height' UIView:0x13fe428e0.height == 568   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x28276f2a0 V:[UIView:0x13fd4b2f0]-(40)-[UIView:0x13fd18a40]   (active)>
rjjhvcjd

rjjhvcjd1#

系统不喜欢将多个约束分配给具有相同优先级的锚,因为它们冲突,并且系统“打破”其中一个以满足至少一个。如果没有另外定义,约束的默认优先级为required(1000)。您可以为锚分配多个约束,并通过为它们分配不同的优先级(如defaultLowdefaultHigh)来激活所需的约束,并代表您切换它们。
第一件事是保持对约束的引用,以便更改它们。请随意将您的代码更新为以下内容:

class MyViewController: UIViewController {

    // ...

    // Keep a reference to the constraints you want to change
    // depending on user interaction or desired state 
    // in your view controller class

    var tableViewConstraintTopAnchor1: NSLayoutConstraint!
    var tableViewConstraintTopAnchor2: NSLayoutConstraint!

    // ...

}

然后在setupViews函数中,分配它们:

func setupViews() {

    // ...

    // adding subviews and other constraints

    // ...

    // MARK -- tableView

    tableView.translatesAutoresizingMaskIntoConstraints=false
    tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive=true
    tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive=true

    // assign (desired, but conflicting) constraints with different priority

    tableViewConstraintTopAnchor1 = tableView.topAnchor.constraint(equalTo: serachBarView.bottomAnchor, constant: 0)
    tableViewConstraintTopAnchor1.priority = .defaultHigh
    tableViewConstraintTopAnchor1.isActive = true

    tableViewConstraintTopAnchor2 = tableView.topAnchor.constraint(equalTo: mypopUpView.bottomAnchor, constant: 0)
    tableViewConstraintTopAnchor2.priority = .defaultLow
    tableViewConstraintTopAnchor2.isActive = true

    tableView.delegate = self
    tableView.dataSource = self
    tableView.register(specialGoodCell.self, forCellReuseIdentifier: "myCell")

}

在labelAction函数中,只需切换约束的优先级,并告诉系统更新视图的布局。

@objc func labelAction(){

    // MARK -- tableView

    // Switch the priority of the desired constraint to defaultHigh
    // the other ones to defaultLow

    tableViewConstraintTopAnchor1.priority = .defaultLow
    tableViewConstraintTopAnchor2.priority = .defaultHigh

    view.setNeedsLayout()
    view.layoutIfNeeded()

}

也可以将其放在UIView动画块中,并将整个内容设置为动画:

@objc func labelAction(){

    // MARK -- tableView

    UIView.animate(withDuration: 0.2) {

         self.tableViewConstraintTopAnchor1.priority = .defaultLow
         self.tableViewConstraintTopAnchor2.priority = .defaultHigh

         self.view.setNeedsLayout()
         self.view.layoutIfNeeded()

    }

}

viewDidLoad()中为tableView分配两个约束(或在其中调用的函数)只有在mypopUpView已经存在并且在同一显示层次结构中时才有效-到目前为止在代码中还没有看到它;)

js4nwp54

js4nwp542#

例如。..在你所做的多重约束中,你有一个前导,一个尾随,然后还有一个宽度。你不能有一个领先的说5,然后一个尾随的-5,但然后还指定一个宽度,因为你已经指定了宽度与领先和尾随约束,如果这是有意义的?如果没有,请告诉我,我会详细解释。基本上如果你的屏幕是300像素宽。你有一个标签,并将其限制为前导50,结尾-50。.则标签宽度将自动变为200。.你不能添加任何东西的宽度锚,因为它不能满足你所有的约束。

相关问题