指定NSLayoutConstraint的UILayoutPriority似乎没有生效

时间:2019-07-10 20:48:45

标签: ios swift uitableview uiscrollview

我在UIScrollView中有一个表和一个按钮,我想要以下设计:

  • 按钮在表的最后一行下方至少 40
  • 按钮始终位于视图末尾上方

在以下限制条件下,我设法使按钮始终始终在表格的最后一行下方40 pts,并且在表格足够长的情况下在视图末端上方83 pt。在我看来,bottomConstraint的优先级没有适当地覆盖topConstraint的约束。我已将滚动视图设置为涵盖整个屏幕。

/* - Sign Out button is 40 pts tall - */
let heightConstraint = NSLayoutConstraint(item: signOutBtn, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 41)

/* - Sign Out button is ALWAYS 83 pts above bottom of screen, when visible - */
let bottomConstraint = NSLayoutConstraint(item: signOutBtn, attribute: .bottom, relatedBy: .equal, toItem: scrollView, attribute: .bottom, multiplier: 1, constant: -83)
bottomConstraint.priority = UILayoutPriority.required

/* - Sign Out button is AT LEAST 40 pts below last row of table - */
let topConstraint = NSLayoutConstraint(item: signOutBtn, attribute: .top, relatedBy: .greaterThanOrEqual, toItem: tableView, attribute: .bottom, multiplier: 1, constant: 40)
topConstraint.priority = UILayoutPriority.defaultLow

/* - Sign Out button stretches across the screen - */
let leadingConstraint = NSLayoutConstraint(item: signOutBtn, attribute: .leading, relatedBy: .equal, toItem: scrollView, attribute: .leading, multiplier: 1, constant: 0)
let trailingConstraint = NSLayoutConstraint(item: signOutBtn, attribute: .trailing, relatedBy: .equal, toItem: scrollView, attribute: .trailing, multiplier: 1, constant: 0)

scrollView.addConstraints([heightConstraint, bottomConstraint, leadingConstraint, trailingConstraint, topConstraint])

屏幕截图:
(不好-这是我现在完成的事情)
enter image description here

(好)
enter image description here enter image description here

如果表格过长,则不会显示“退出”按钮,用户需要向下滚动至该按钮。

enter image description here

2 个答案:

答案 0 :(得分:0)

我创建了以下视图控制器,该控制器应该可以解决您的问题-我必须承认,我不知道为什么在布局中使用了scrollView,但是我希望我能够重新创建您的设置。

为了模拟不同的桌子高度,我使用了tableView.heightAnchor.constraint(equalToConstant: 300)

Anchors用于创建约束。

import UIKit

class ViewController: UIViewController {
    let scrollView = UIScrollView()
    let tableView = UITableView()
    let signOutBtn = UIButton()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(scrollView)
        scrollView.addSubview(tableView)
        scrollView.addSubview(signOutBtn)

        tableView.dataSource = self

        signOutBtn.setTitle("BUTTON", for: .normal)
        signOutBtn.setTitleColor(.blue, for: .normal)

        //ScrollView constraints
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor)
        ])

        //TableView constraints
        tableView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.topAnchor),
            tableView.bottomAnchor.constraint(lessThanOrEqualTo: signOutBtn.topAnchor, constant: -40),
            tableView.heightAnchor.constraint(equalToConstant: 300),
            tableView.trailingAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.trailingAnchor),
            tableView.leadingAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.leadingAnchor)
        ])

        //SignOutButton constraints
        signOutBtn.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            signOutBtn.heightAnchor.constraint(equalToConstant: 41),
            signOutBtn.bottomAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.bottomAnchor, constant: -83),
            signOutBtn.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        ])

    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 30
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .default, reuseIdentifier: "")
        cell.textLabel?.text = "\(indexPath.row)"
        return cell
    }
}

我还将屏幕附加结果:

Image with table with elements fitting view

Image with table with elements not fitting view

答案 1 :(得分:0)

要回答有关约束优先级的特定问题...

您对滚动视图如何使用约束感到困惑。

在此图像中,Label约束在滚动视图的顶部,Button约束在标签的优先级为250点的标签(优先级为250),而Button约束在滚动视图的底部为优先级1000的83点。 >

受约束的底部确定滚动视图内容的.contentSize高度-或“可滚动区域”:

enter image description here