Swift 中 NSLayoutConstraints 的奇怪行为
Posted
技术标签:
【中文标题】Swift 中 NSLayoutConstraints 的奇怪行为【英文标题】:Strange behaviour of NSLayoutConstraints in Swift 【发布时间】:2018-09-26 13:18:41 【问题描述】:我的视图顶部有一个 textField,而 tableView 应该放在 textField 下方。
所以我添加它们的代码如下:
private func setupSearchBar()
searchtextField = UITextField()
mapView.addSubview(searchtextField)
searchtextField.translatesAutoresizingMaskIntoConstraints = false
let constraints = [
NSLayoutConstraint(item: searchtextField, attribute: .leading, relatedBy: .equal, toItem: mapView.safeAreaLayoutGuide, attribute: .leading, multiplier: 1.0, constant: 16.0),
NSLayoutConstraint(item: searchtextField, attribute: .trailing, relatedBy: .equal, toItem: mapView.safeAreaLayoutGuide, attribute: .trailing, multiplier: 1.0, constant: -16.0),
NSLayoutConstraint(item: searchtextField, attribute: .top, relatedBy: .equal, toItem: mapView.safeAreaLayoutGuide, attribute: .top, multiplier: 1.0, constant: 24.0),
NSLayoutConstraint(item: searchtextField, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 46.0)
]
NSLayoutConstraint.activate(constraints)
在此之后我正在设置我的 tableView:
private func setupResultsTableView()
tableView = UITableView()
mapView.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableViewHeightAnchor = tableView.heightAnchor.constraint(equalToConstant: 0)
let constraints = [
tableView.safeAreaLayoutGuide.topAnchor.constraint(equalTo: searchtextField.safeAreaLayoutGuide.bottomAnchor),
tableView.safeAreaLayoutGuide.leadingAnchor.constraint(equalTo: mapView.safeAreaLayoutGuide.leadingAnchor),
tableView.safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: mapView.trailingAnchor),
tableViewHeightAnchor!,
tableView.safeAreaLayoutGuide.bottomAnchor.constraint(lessThanOrEqualToSystemSpacingBelow: view.safeAreaLayoutGuide.bottomAnchor, multiplier: 1.0)
]
NSLayoutConstraint.activate(constraints)
我想做的是: 1.设置tableView高度为0 2.当用户开始输入我的textField时,根据搜索结果显示tablView并将其高度设置为tableView的contentSize。所以最大尺寸会贴在设备底部,如果有1-2个结果显示,那么就让tableView变小。
当用户开始输入时,我运行下一个:
func textFieldDidBeginEditing(_ textField: UITextField)
filterContentForSearchText(textField.text!)
tableView.reloadData()
UIView.animate(withDuration: 0.6)
self.tableView.layoutIfNeeded()
if textField.isEditing
self.tableViewHeightAnchor.constant = self.tableView.contentSize.height
else
self.tableViewHeightAnchor.constant = 0.0
但是我的代码有问题,因为我得到了如此丑陋的结果: 当我开始向上滑动时,tableView 开始向上并越过我的 textField
当我完成滚动时,它会停在视图中间
有没有办法解决这个问题?有什么问题可以问我
【问题讨论】:
"将其高度设置为 contentSize" 这个计算似乎是错误的。这就是为什么您的表格视图单元格在视图中间结束的原因。您不应该设置 tableView IMO 的 contentsize。它自己照顾它。 @RakeshaShastri 但我想动态调整 tableView 的高度 设置tableview的contentsize会如何减小tableview的尺寸? @RakeshaShastri 啊不,我将 tableView 的高度设置为其 contentSize。让我更新我的代码 我在任何地方都看不到该代码。 【参考方案1】:让我们设置 tableView 全高并切换其可见性,如下所示:
tableView.backgroundColor = .clear
tableView.isHidden = true
tableView.tableFooterView = UIView()
对于 tableView 有这些约束:
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: searchtextField.bottomAnchor),
tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, multiplier: 1.0)
])
现在我们可以使用UITextFieldDelegate
方法来切换我们的tableView:
func textFieldDidBeginEditing(_ textField: UITextField)
self.toggleSearch(true)
func textFieldShouldReturn(_ textField: UITextField) -> Bool
textField.resignFirstResponder()
return true
func textFieldDidEndEditing(_ textField: UITextField)
self.toggleSearch(false)
private func toggleSearch(_ value: Bool)
self.tableView.isHidden = !value
别忘了设置searchtextField.delegate = self
另外,您可以添加一个半透明的 backgroundView 并使用这个动画版本的toggleSearch
来淡入/淡出 tableView:
let backgroundView = UIView()
backgroundView.backgroundColor = UIColor.black.withAlphaComponent(0.3)
backgroundView.layer.opacity = 0
tableView.backgroundView = backgroundView
private func toggleSearch(_ value: Bool)
var completionBlock: ((Bool) -> Void)?
if (value)
self.tableView.isHidden = false
else
completionBlock = [weak self] _ in self?.tableView.isHidden = true
UIView.animate(withDuration: 0.3, animations:
self.tableView.backgroundView?.layer.opacity = value ? 1 : 0
, completion: completionBlock)
【讨论】:
非常感谢!它对我帮助很大,但我遇到了一些问题,当我的 tableView 只有一行时 - 我无法选择它,但当它们很少时是可能的,例如 2+。你能告诉我问题是什么或可能是什么吗? 无法选择你的意思是tableView(_ tableView: UITableView, didSelectRowAt indexPath
没有被调用?可能是覆盖 tableView 顶部的视图,或者带有单元格的东西,尝试在模拟器中运行并查看 Debug View Hierarchy
或此 teamtreehouse.com/community/… 或此 ***.com/a/33226911/1244597 不能确定,如果没有任何帮助,请创建一个要点.swift 文件并分享链接以上是关于Swift 中 NSLayoutConstraints 的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章