我有以下通过编程构建的Booking类(UIView),但无法使其滚动。我要求它只能垂直滚动。我不使用UIStackView,因为我实际使用的视图比下面的代码稍微复杂一些。下面提供的代码是简化版本。
我阅读了各种SO帖子,其中一些人说您需要在滚动视图内部包含一个包含所有子视图的视图(我目前正在这样做),其他人则说不需要。有人说您需要手动定义滚动视图的内容大小,而另一些人则说您不必这样做!这些观点中的每一个都正确吗?还是没关系?
当我将UIScrollView更新为所有视图高度的总和时,我看到垂直滚动指示器会上下移动,但实际内容不会移动!
如果已经设置了约束,那么scrollview应该能够计算高度吗?
我还遇到了视图在垂直方向上拉伸的问题,因此在设置约束时添加了具有优先权的内容。
这是代码:-
import UIKit
@IBDesignable
class Booking: UIView, UIScrollViewDelegate {
//Layout Items
let scrollView: UIScrollView = {
let view = UIScrollView()
view.translatesAutoresizingMaskIntoConstraints = false
view.showsVerticalScrollIndicator = true
view.showsHorizontalScrollIndicator = false
view.isScrollEnabled = true
return view
}()
let contentView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
//Header view and its children
let headerContentView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1)
return view
}()
let headerBookingLbl: UILabel = {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.textColor = UIColor.white
view.numberOfLines = 3
view.textAlignment = .center
view.text = "Title Title Title"
return view
}()
let aboutStack: UIStackView = {
let view = UIStackView()
view.isUserInteractionEnabled = true
view.translatesAutoresizingMaskIntoConstraints = false
view.axis = .horizontal
view.alignment = .fill
view.distribution = .fill
view.spacing = 5
view.backgroundColor = UIColor.clear
return view
}()
let aboutIcon: UIImageView = {
let view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
view.contentMode = .scaleAspectFit
view.clipsToBounds = true
view.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0)
return view
}()
let aboutLbl: UILabel = {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.textColor = UIColor.white
view.text = "About Your Booking"
view.numberOfLines = 1
view.textAlignment = .natural
return view
}()
//body view
let haveABookingLbl: UILabel = {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.textColor = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1)
view.text = "Already have a booking?"
view.numberOfLines = 0
view.textAlignment = .center
return view
}()
let enterABookingInfoLbl: UILabel = {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.textColor = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1)
view.text = "Enter your ticket reference number to gain access to bonus content"
view.numberOfLines = 0
view.textAlignment = .center
return view
}()
let bookingReference: UITextField = {
let view = UITextField()
view.translatesAutoresizingMaskIntoConstraints = false
view.autocapitalizationType = .none
view.borderStyle = UITextField.BorderStyle.roundedRect
view.placeholder = "Ticket reference*"
return view
}()
let lastName: UITextField = {
let view = UITextField()
view.translatesAutoresizingMaskIntoConstraints = false
view.autocapitalizationType = .none
view.borderStyle = UITextField.BorderStyle.roundedRect
view.placeholder = "Last name*"
return view
}()
let submitBtn: UIButton = {
let view = UIButton()
view.translatesAutoresizingMaskIntoConstraints = false
view.setTitle("Submit", for: .normal)
view.backgroundColor = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1)
return view
}()
let viewPrivacyPolicayLbl: UILabel = {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.isUserInteractionEnabled = true
view.textColor = UIColor.black
view.numberOfLines = 1
view.textAlignment = .center
//underline the text - use attributed string
let text = "view privacy policy"
let underlinedText = NSMutableAttributedString(string: text)
underlinedText.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: NSRange(location: 0, length: text.count))
view.attributedText = underlinedText
return view
}()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func layoutSubviews() {
super.layoutSubviews()
}
//This override should prevent issue where you can drag scrollview 1px left/right which shows a white area behind the poster.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
scrollView.contentOffset.x = 0
}
private func setup() {
print("setup()")
setupViews()
setupConstraints()
//scrollView.contentSize = contentView.bounds.size ?? is this needed? doesnt seem to work!
scrollView.delegate = self
}
private func setupViews() {
print("setupViews()")
//Add root scroll view
addSubview(scrollView)
scrollView.addSubview(contentView)
//header contents
contentView.addSubview(headerContentView)
headerContentView.addSubview(headerBookingLbl)
headerContentView.addSubview(aboutStack)
aboutStack.addArrangedSubview(aboutIcon)
aboutStack.addArrangedSubview(aboutLbl)
//body contents
contentView.addSubview(haveABookingLbl)
contentView.addSubview(enterABookingInfoLbl)
contentView.addSubview(bookingReference)
contentView.addSubview(lastName)
contentView.addSubview(submitBtn)
contentView.addSubview(viewPrivacyPolicayLbl)
} //setupViews
private func setupConstraints() {
print("setupConstraints()")
let scrollViewConstraints = [
scrollView.topAnchor.constraint(equalTo: topAnchor),
scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
scrollView.widthAnchor.constraint(equalTo: widthAnchor),
scrollView.centerXAnchor.constraint(equalTo: centerXAnchor),
contentView.centerXAnchor.constraint(equalTo: centerXAnchor),
contentView.widthAnchor.constraint(equalTo: widthAnchor),
contentView.topAnchor.constraint(equalTo: topAnchor),
contentView.bottomAnchor.constraint(equalTo: bottomAnchor),
]
NSLayoutConstraint.activate(scrollViewConstraints)
//header
let headerViewConstraints = [
//container
headerContentView.topAnchor.constraint(equalTo: topAnchor),
headerContentView.leadingAnchor.constraint(equalTo: leadingAnchor),
headerContentView.trailingAnchor.constraint(equalTo: trailingAnchor),
//headerBookingLbl
headerBookingLbl.topAnchor.constraint(equalTo: headerContentView.topAnchor, constant: 20),
headerBookingLbl.leadingAnchor.constraint(equalTo: headerContentView.leadingAnchor, constant: 20),
headerBookingLbl.trailingAnchor.constraint(equalTo: headerContentView.trailingAnchor, constant: -20),
//aboutStack
aboutStack.topAnchor.constraint(equalTo: headerBookingLbl.bottomAnchor, constant: 20),
aboutStack.centerXAnchor.constraint(equalTo: headerContentView.centerXAnchor),
aboutStack.bottomAnchor.constraint(equalTo: headerContentView.bottomAnchor, constant: -20)
]
NSLayoutConstraint.activate(headerViewConstraints)
headerBookingLbl.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
//body
let bodyViewConstraints = [
//haveABookingLbl
haveABookingLbl.topAnchor.constraint(equalTo: headerContentView.bottomAnchor, constant: 30),
haveABookingLbl.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 60),
haveABookingLbl.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -60),
//enterABookingInfoLbl
enterABookingInfoLbl.centerXAnchor.constraint(equalTo: centerXAnchor),
enterABookingInfoLbl.topAnchor.constraint(equalTo: haveABookingLbl.bottomAnchor, constant: 15),
enterABookingInfoLbl.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 60),
enterABookingInfoLbl.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -60),
//bookingReference
bookingReference.heightAnchor.constraint(equalToConstant: 40),
bookingReference.centerXAnchor.constraint(equalTo: centerXAnchor),
bookingReference.topAnchor.constraint(equalTo: enterABookingInfoLbl.bottomAnchor, constant: 15),
bookingReference.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 60),
bookingReference.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -60),
//lastName
lastName.heightAnchor.constraint(equalToConstant: 40),
lastName.centerXAnchor.constraint(equalTo: centerXAnchor),
lastName.topAnchor.constraint(equalTo: bookingReference.bottomAnchor, constant: 15),
lastName.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 60),
lastName.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -60),
//submitBtn
submitBtn.centerXAnchor.constraint(equalTo: centerXAnchor),
submitBtn.topAnchor.constraint(equalTo: lastName.bottomAnchor, constant: 15),
submitBtn.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 60),
submitBtn.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -60),
viewPrivacyPolicayLbl.centerXAnchor.constraint(equalTo: centerXAnchor),
viewPrivacyPolicayLbl.topAnchor.constraint(equalTo: submitBtn.bottomAnchor, constant: 15),
viewPrivacyPolicayLbl.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 60),
viewPrivacyPolicayLbl.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -60),
//viewPrivacyPolicayLbl.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -20)
]
NSLayoutConstraint.activate(bodyViewConstraints)
//Set hugging priority to prevent said items from being made larger than their intrinsic size
haveABookingLbl.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
enterABookingInfoLbl.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
submitBtn.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
viewPrivacyPolicayLbl.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
} //setupConstraints
}
答案 0 :(得分:1)
在滚动视图内添加内容视图的主要原因是使自动布局正常工作。内容视图必须填充滚动视图,添加到内容视图的每个子视图都需要使用其容器作为参考以正确的方式设置约束:
private func setupConstraints() {
print("setupConstraints()")
let scrollViewConstraints = [
scrollView.topAnchor.constraint(equalTo: topAnchor),
scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
scrollView.widthAnchor.constraint(equalTo: widthAnchor),
scrollView.centerXAnchor.constraint(equalTo: centerXAnchor),
contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor)
]
NSLayoutConstraint.activate(scrollViewConstraints)
// header
let headerViewConstraints = [
// container
headerContentView.topAnchor.constraint(equalTo: contentView.topAnchor),
headerContentView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
headerContentView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
// headerBookingLbl
headerBookingLbl.topAnchor.constraint(equalTo: headerContentView.topAnchor, constant: 20),
headerBookingLbl.leadingAnchor.constraint(equalTo: headerContentView.leadingAnchor, constant: 20),
headerBookingLbl.trailingAnchor.constraint(equalTo: headerContentView.trailingAnchor, constant: -20),
// aboutStack
aboutStack.topAnchor.constraint(equalTo: headerBookingLbl.bottomAnchor, constant: 20),
aboutStack.centerXAnchor.constraint(equalTo: headerContentView.centerXAnchor),
aboutStack.bottomAnchor.constraint(equalTo: headerContentView.bottomAnchor, constant: -20)
]
NSLayoutConstraint.activate(headerViewConstraints)
headerBookingLbl.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
// body
let bodyViewConstraints = [
// haveABookingLbl
haveABookingLbl.topAnchor.constraint(equalTo: headerContentView.bottomAnchor, constant: 30),
haveABookingLbl.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 60),
haveABookingLbl.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -60),
// enterABookingInfoLbl
enterABookingInfoLbl.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
enterABookingInfoLbl.topAnchor.constraint(equalTo: haveABookingLbl.bottomAnchor, constant: 15),
enterABookingInfoLbl.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 60),
enterABookingInfoLbl.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -60),
// bookingReference
bookingReference.heightAnchor.constraint(equalToConstant: 40),
bookingReference.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
bookingReference.topAnchor.constraint(equalTo: enterABookingInfoLbl.bottomAnchor, constant: 15),
bookingReference.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 60),
bookingReference.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -60),
// lastName
lastName.heightAnchor.constraint(equalToConstant: 40),
lastName.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
lastName.topAnchor.constraint(equalTo: bookingReference.bottomAnchor, constant: 15),
lastName.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 60),
lastName.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -60),
// submitBtn
submitBtn.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
submitBtn.topAnchor.constraint(equalTo: lastName.bottomAnchor, constant: 15),
submitBtn.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 60),
submitBtn.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -60),
viewPrivacyPolicayLbl.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
viewPrivacyPolicayLbl.topAnchor.constraint(equalTo: submitBtn.bottomAnchor, constant: 15),
viewPrivacyPolicayLbl.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 60),
viewPrivacyPolicayLbl.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -60),
viewPrivacyPolicayLbl.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20)
]
NSLayoutConstraint.activate(bodyViewConstraints)
// Set hugging priority to prevent said items from being made larger than their intrinsic size
haveABookingLbl.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
enterABookingInfoLbl.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
submitBtn.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
viewPrivacyPolicayLbl.setContentHuggingPriority(UILayoutPriority(rawValue: 1000), for: .vertical)
} // setupConstraints
答案 1 :(得分:0)
根据内容大小设置滚动视图的高度,并将滚动视图的宽度设置为当前视图的宽度:-
let contentHeight = 700(depends on your requirement)
scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width, height: contentHeight)