我想将视图控制器添加为 UIView 内的子视图。我已经给出了所需的约束,但我不明白为什么它重叠。这是它的最少代码。我已经给出了顶部、底部、前导、尾随约束,但不确定为什么它重叠。 我想把svc放在parentView下面
override func viewDidLoad() {
super.viewDidLoad()
let parentView = parentView()
parentView.configure(movieDetails: movieDetails)
let svc = SmiliarMovieViewController(viewModel: viewModel)
addChild(svc)
svc.view.translatesAutoresizingMaskIntoConstraints = false
parentView.addSubview(svc.view)
svc.didMove(toParent: self)
NSLayoutConstraint.activate([
parentView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
parentView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
parentView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
svc.view.topAnchor.constraint(equalTo: parentView.bottomAnchor),
svc.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
svc.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
svc.view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
])
}
private class parentView: UIView {
// code for parent view...
}
这是完整的代码..
final class MovieDetailsDisplayViewController: UIViewController {
let movieDetails: MovieDetails
let viewModel: MoviesDetailsViewModel
init(movieDetails: MovieDetails, viewModel: MoviesDetailsViewModel) {
self.movieDetails = movieDetails
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
view = parentView()
}
override func viewDidLoad() {
super.viewDidLoad()
let uiView = parentView()
(view as? parentView)?.configure(movieDetails: movieDetails)
let svc = SmiliarMovieViewController(viewModel: viewModel)
view.addSubview(uiView)
uiView.addSubview(svc.view)
NSLayoutConstraint.activate([
uiView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
uiView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
uiView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
uiView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
svc.view.topAnchor.constraint(equalTo: uiView.bottomAnchor),
svc.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
svc.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
svc.view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
])
}
private class parentView: UIView {
let scrollView = UIScrollView()
let backdropImageView = UIImageView()
let titleLabel = UILabel()
let overviewLabel = UILabel()
private lazy var contentStackView = UIStackView(arrangedSubviews: [backdropImageView, titleLabel, overviewLabel])
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
backgroundColor = .white
backdropImageView.contentMode = .scaleAspectFill
backdropImageView.clipsToBounds = true
titleLabel.font = UIFont.Heading.medium
titleLabel.textColor = UIColor.Text.charcoal
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
titleLabel.setContentHuggingPriority(.required, for: .vertical)
overviewLabel.font = UIFont.Body.small
overviewLabel.textColor = UIColor.Text.grey
overviewLabel.numberOfLines = 0
overviewLabel.lineBreakMode = .byWordWrapping
contentStackView.axis = .vertical
contentStackView.spacing = 24
contentStackView.setCustomSpacing(8, after: titleLabel)
setupViewsHierarchy()
setupConstraints()
}
private func setupViewsHierarchy() {
addSubview(scrollView)
scrollView.addSubview(contentStackView)
}
private func setupConstraints() {
scrollView.translatesAutoresizingMaskIntoConstraints = false
backdropImageView.translatesAutoresizingMaskIntoConstraints = false
contentStackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(
[
scrollView.topAnchor.constraint(equalTo: topAnchor),
scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
backdropImageView.heightAnchor.constraint(equalTo: backdropImageView.widthAnchor, multiplier: 11 / 16, constant: 0),
contentStackView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 24),
contentStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
contentStackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
contentStackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -24)
]
)
scrollView.layoutMargins = UIEdgeInsets(top: 24, left: 16, bottom: 24, right: 16)
preservesSuperviewLayoutMargins = false
}
func configure(movieDetails: MovieDetails) {
backdropImageView.dm_setImage(backdropPath: movieDetails.backdropPath)
titleLabel.text = movieDetails.title
overviewLabel.text = movieDetails.overview
}
}
}
这是崩溃的屏幕截图..
非常非常快速的使用子视图控制器的示例......
我们将从您的“相似”视图控制器开始。集合视图单元和创建集合视图的视图控制器:
class MySimilarCell: UICollectionViewCell {
let imgView = UIImageView()
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
[imgView, label].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(v)
}
let g = contentView.layoutMarginsGuide
NSLayoutConstraint.activate([
imgView.topAnchor.constraint(equalTo: g.topAnchor),
imgView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
imgView.trailingAnchor.constraint(equalTo: g.trailingAnchor),
label.topAnchor.constraint(equalTo: imgView.bottomAnchor, constant: 4.0),
label.leadingAnchor.constraint(equalTo: g.leadingAnchor),
label.trailingAnchor.constraint(equalTo: g.trailingAnchor),
label.bottomAnchor.constraint(equalTo: g.bottomAnchor),
])
imgView.backgroundColor = .systemRed
imgView.tintColor = .white
label.textAlignment = .center
}
}
class MySimilarViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var cv: UICollectionView!
let data: [String] = [
"A", "B", "C", "D", "E", "F", "G", "H"
]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
let fl = UICollectionViewFlowLayout()
fl.scrollDirection = .horizontal
fl.itemSize = .init(width: 120.0, height: 180.0)
cv = UICollectionView(frame: .zero, collectionViewLayout: fl)
cv.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(cv)
// so we don't have to type so much
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
cv.topAnchor.constraint(equalTo: g.topAnchor),
cv.leadingAnchor.constraint(equalTo: g.leadingAnchor),
cv.trailingAnchor.constraint(equalTo: g.trailingAnchor),
cv.heightAnchor.constraint(equalToConstant: 180.0),
])
cv.dataSource = self
cv.delegate = self
cv.register(MySimilarCell.self, forCellWithReuseIdentifier: "c")
// so we can see the collection view framing
cv.backgroundColor = .cyan
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let c = collectionView.dequeueReusableCell(withReuseIdentifier: "c", for: indexPath) as! MySimilarCell
if let img = UIImage(systemName: "\(data[indexPath.item].lowercased()).circle") {
c.imgView.image = img
}
c.label.text = data[indexPath.item]
return c
}
}
如果您将
MySimilarViewController
设置为初始视图控制器并运行应用程序,它应该如下所示:
接下来,我们将在垂直堆栈视图中、滚动视图中设置“父”控制器,其中包含图像视图、标题标签和段落标签,底部留有“子”控制器的空间:
class MyMainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
// add an image view, title label, paragraph label
// to a vertical stack view
// added to a scroll view
let imgView = UIImageView()
imgView.backgroundColor = .white
imgView.tintColor = .systemOrange
if let img = UIImage(systemName: "swift") {
imgView.image = img
}
let titleLabel = UILabel()
titleLabel.backgroundColor = .green
titleLabel.font = .systemFont(ofSize: 28.0, weight: .bold)
titleLabel.text = "Spirited Away"
let paraLabel = UILabel()
paraLabel.backgroundColor = .green
paraLabel.font = .systemFont(ofSize: 20.0, weight: .regular)
paraLabel.numberOfLines = 0
paraLabel.text = "A young girl, Chihiro, becomes trapped in a strange new world of spirits. When her parents undergo a mysterious transformation, she must call upon the courage she never knew she had to free her family."
let stackView = UIStackView()
stackView.axis = .vertical
stackView.spacing = 20.0
stackView.addArrangedSubview(imgView)
stackView.addArrangedSubview(titleLabel)
stackView.addArrangedSubview(paraLabel)
let scrollView = UIScrollView()
// so we can see the scroll view's framing
scrollView.backgroundColor = .systemYellow
stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(stackView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
let addHereView = UIView()
addHereView.backgroundColor = .systemBlue
addHereView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(addHereView)
// so we don't have to type so much
let g = view.safeAreaLayoutGuide
let cg = scrollView.contentLayoutGuide
let fg = scrollView.frameLayoutGuide
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
scrollView.bottomAnchor.constraint(equalTo: addHereView.topAnchor, constant: -20.0),
stackView.topAnchor.constraint(equalTo: cg.topAnchor, constant: 20.0),
stackView.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 20.0),
stackView.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -20.0),
stackView.bottomAnchor.constraint(equalTo: cg.bottomAnchor, constant: -20.0),
stackView.widthAnchor.constraint(equalTo: fg.widthAnchor, constant: -40.0),
// image view needs height
imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor, multiplier: 1.0),
addHereView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
addHereView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
addHereView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -20.0),
// height of the child content
addHereView.heightAnchor.constraint(equalToConstant: 180.0),
])
}
}
现在,如果我们将
MyMainViewController
设置为初始视图控制器,我们应该得到:
图像和标签位于(黄色)滚动视图中,我们有一个蓝色视图,我们将在其中添加子控制器的视图。
因此,在
viewDidLoad()
中的MyMainViewController
末尾,我们将添加以下内容:
let similarVC = MySimilarViewController()
addChild(similarVC)
// safely unwrap MySimilarViewController's view
guard let similarView = similarVC.view else {
// this should never happen, unless we've really mis-written the detail view controller
fatalError("Similar VC had no view!!!")
}
similarView.translatesAutoresizingMaskIntoConstraints = false
addHereView.addSubview(similarView)
NSLayoutConstraint.activate([
similarView.topAnchor.constraint(equalTo: addHereView.topAnchor, constant: 0.0),
similarView.leadingAnchor.constraint(equalTo: addHereView.leadingAnchor, constant: 0.0),
similarView.trailingAnchor.constraint(equalTo: addHereView.trailingAnchor, constant: 0.0),
similarView.bottomAnchor.constraint(equalTo: addHereView.bottomAnchor, constant: 0.0),
])
similarVC.didMove(toParent: self)
因此,我们添加了
MySimilarViewController
的实例作为子视图控制器,并将其 view
添加为蓝色视图的子视图。
我们得到这个: