ios - UIScrollView 的子视图保持在同一位置,而 UIScrollView 垂直滚动
问题描述
谁能告诉我为什么我添加到 UIScrollView 的子视图不会滚动?当我运行项目时,我可以上下滚动 UIScrollView,当我滚动时,我可以在屏幕右侧看到滚动指示器。但是我添加到 UIScrollView 的子视图保持在相同的位置,就好像它们根本不是 UIScrollView 的子视图一样。这很奇怪,因为我从我正在使用的另一个视图中复制了大部分代码,并且它的工作方式完全符合预期,只是这个视图不起作用。感谢观看,这是我的代码
import UIKit
class EnterCredentialsVC2: UIViewController {
private lazy var scrollView: UIScrollView = { [unowned self] in
let view = UIScrollView()
view.backgroundColor = UIColor.ricdBlue
view.contentSize.height = self.view.frame.size.height + 300
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let emailTextField: UITextField = {
let field = UITextField()
field.placeholder = "Email Address"
field.translatesAutoresizingMaskIntoConstraints = false
return field
}()
private let passwordTextField: UITextField = {
let field = UITextField()
field.placeholder = "Password (6 characters minimum)"
field.translatesAutoresizingMaskIntoConstraints = false
return field
}()
private let enterButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
private let errorLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.minimumScaleFactor = 0.1
label.adjustsFontSizeToFitWidth = true
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
layoutView()
}
}
//view layout methods
extension EnterCredentialsVC2 {
private func layoutView() {
layoutScrollView()
layoutEmailTextField()
layoutPasswordTextField()
layoutEnterButton()
layoutErrorLabel()
}
private func layoutScrollView() {
view.addSubview(scrollView)
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
scrollView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
private func layoutEmailTextField() {
scrollView.addSubview(emailTextField)
emailTextField.heightAnchor.constraint(equalToConstant: 45).isActive = true
emailTextField.widthAnchor.constraint(equalToConstant: view.bounds.width * 0.9).isActive = true
emailTextField.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
emailTextField.topAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.topAnchor, constant: 100).isActive = true
}
private func layoutPasswordTextField() {
scrollView.addSubview(passwordTextField)
passwordTextField.heightAnchor.constraint(equalToConstant: 45).isActive = true
passwordTextField.widthAnchor.constraint(equalToConstant: view.bounds.width * 0.9).isActive = true
passwordTextField.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
passwordTextField.topAnchor.constraint(equalTo: emailTextField.bottomAnchor, constant: 50).isActive = true
}
private func layoutEnterButton() {
scrollView.addSubview(enterButton)
enterButton.widthAnchor.constraint(equalToConstant: view.bounds.width * 0.5).isActive = true
enterButton.heightAnchor.constraint(equalToConstant: 55).isActive = true
enterButton.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
let top = enterButton.topAnchor.constraint(equalTo: passwordTextField.bottomAnchor, constant: 50)
top.priority = .defaultHigh
top.isActive = true
let bottom = enterButton.bottomAnchor.constraint(greaterThanOrEqualTo: scrollView.safeAreaLayoutGuide.bottomAnchor, constant: 200)
bottom.priority = .defaultLow
bottom.isActive = true
}
private func layoutErrorLabel() {
scrollView.addSubview(errorLabel)
errorLabel.widthAnchor.constraint(equalToConstant: view.bounds.width-20).isActive = true
errorLabel.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
let top = errorLabel.topAnchor.constraint(equalTo: enterButton.bottomAnchor, constant: 30)
top.priority = .required
top.isActive = true
let bottom = errorLabel.bottomAnchor.constraint(equalTo: scrollView.safeAreaLayoutGuide.bottomAnchor, constant: -20)
bottom.priority = .defaultLow
bottom.isActive = true
}
}
解决方案
滚动视图内的直接子视图的约束以一种特殊的方式工作。它们必须固定到滚动视图本身或其contentLayoutGuide
. 这有一个特殊的含义:“我并没有真正固定在您的外部,我只是向您展示子视图的布局,并告诉您您的内容大小。”
固定到安全区域布局指南——一个永远不会移动的东西——完全违反了这一点。这就像固定到滚动视图的frameLayoutGuide
,或者完全固定到滚动视图之外的东西。它特别指示滚动视图在计算内容高度时不要考虑这些视图。
您已经明确地为滚动视图指定了内容大小——在错误的时间以错误的方式,但这是另一回事——并且“幸运地”导致滚动视图可滚动。但是,如果您正确设置了内部约束,则任何显式设置contentSize
都会被忽略。
推荐阅读
- android - Android无法使用google api检索附近的地方
- multithreading - 两个线程同时增加原子整数到底发生了什么
- python - 合并两个 DataFrame 表,使用 Pandas 聚合数据
- html - 将 div 居中放在 div 中。里面的 div 必须小于父 div。引导程序 4
- apache-camel - Apache Camel 请求-回复模式故障超过 3 个或更多微服务
- javascript - 解析具有包含 html 标记的属性的编码 php 对象
- postgresql - 多列索引不用于仅索引扫描,但部分索引是
- ios - 从视图控制器的分离文件中呈现视图控制器
- asp.net-mvc-5.2 - ASP MVC 5 - 用户可以独立更改多个部分视图的顺序
- python - 将数组相乘的最佳方法是什么?在 Python 中