![](/img/trans.png)
[英]Adding UILabel to ScrollView Programmatically with AutoLayout (swift)
[英]Using ScrollView Programmatically in Swift 3
我已经搜索了其他问题,但似乎仍然在使用 swift 3 中的自动布局以编程方式创建我的 scrollView 时遇到一些问题。我能够让我的 scrollview 显示如下图所示,但是当我滚动到底部时,我的其他标签确实显示了不会出现,并且“滚动顶部”标签不会消失。
希望有人可以帮助查看下面的代码!
import UIKit
class ViewController: UIViewController {
let labelOne: UILabel = {
let label = UILabel()
label.text = "Scroll Top"
label.backgroundColor = .red
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let labelTwo: UILabel = {
let label = UILabel()
label.text = "Scroll Bottom"
label.backgroundColor = .green
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
let screensize: CGRect = UIScreen.main.bounds
let screenWidth = screensize.width
let screenHeight = screensize.height
var scrollView: UIScrollView!
scrollView = UIScrollView(frame: CGRect(x: 0, y: 120, width: screenWidth, height: screenHeight))
scrollView.contentSize = CGSize(width: screenWidth, height: 2000)
scrollView.addSubview(labelOne)
scrollView.addSubview(labelTwo)
view.addSubview(labelOne)
view.addSubview(labelTwo)
view.addSubview(scrollView)
// Visual Format Constraints
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": labelOne]))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-100-[v0]", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": labelOne]))
// Using iOS 9 Constraints in order to place the label past the iPhone 7 view
view.addConstraint(NSLayoutConstraint(item: labelTwo, attribute: .top, relatedBy: .equal, toItem: labelOne, attribute: .bottom, multiplier: 1, constant: screenHeight + 200))
view.addConstraint(NSLayoutConstraint(item: labelTwo, attribute: .right, relatedBy: .equal, toItem: labelOne, attribute: .right, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: labelTwo, attribute: .left, relatedBy: .equal, toItem: labelOne, attribute: .left, multiplier: 1, constant: 0)
}
}
使用约束来定义滚动内容的大小很容易——因此您不必进行任何手动计算。
只记得:
contentSize
- 但它们是通过底部和右侧约束来实现的。这是一个简单的示例,它将直接在 Playground 页面中运行:
import UIKit
import PlaygroundSupport
class TestViewController : UIViewController {
let labelOne: UILabel = {
let label = UILabel()
label.text = "Scroll Top"
label.backgroundColor = .red
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let labelTwo: UILabel = {
let label = UILabel()
label.text = "Scroll Bottom"
label.backgroundColor = .green
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .cyan
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
// add the scroll view to self.view
self.view.addSubview(scrollView)
// constrain the scroll view to 8-pts on each side
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8.0).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8.0).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0).isActive = true
// add labelOne to the scroll view
scrollView.addSubview(labelOne)
// constrain labelOne to left & top with 16-pts padding
// this also defines the left & top of the scroll content
labelOne.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 16.0).isActive = true
labelOne.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 16.0).isActive = true
// add labelTwo to the scroll view
scrollView.addSubview(labelTwo)
// constrain labelTwo at 400-pts from the left
labelTwo.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 400.0).isActive = true
// constrain labelTwo at 1000-pts from the top
labelTwo.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 1000).isActive = true
// constrain labelTwo to right & bottom with 16-pts padding
labelTwo.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: -16.0).isActive = true
labelTwo.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -16.0).isActive = true
}
}
let vc = TestViewController()
vc.view.backgroundColor = .yellow
PlaygroundPage.current.liveView = vc
编辑——因为这个答案仍然偶尔会受到关注,我更新了代码以使用更现代的语法,尊重安全区域,并使用滚动视图的.contentLayoutGuide
:
class TestViewController : UIViewController {
let labelOne: UILabel = {
let label = UILabel()
label.text = "Scroll Top"
label.backgroundColor = .yellow
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let labelTwo: UILabel = {
let label = UILabel()
label.text = "Scroll Bottom"
label.backgroundColor = .green
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .cyan
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
// add the scroll view to self.view
self.view.addSubview(scrollView)
// add labelOne to the scroll view
scrollView.addSubview(labelOne)
// add labelTwo to the scroll view
scrollView.addSubview(labelTwo)
// always a good idea to respect safe area
let safeG = view.safeAreaLayoutGuide
// we want to constrain subviews to the scroll view's Content Layout Guide
let contentG = scrollView.contentLayoutGuide
NSLayoutConstraint.activate([
// constrain the scroll view to safe area with 8-pts on each side
scrollView.topAnchor.constraint(equalTo: safeG.topAnchor, constant: 8.0),
scrollView.leadingAnchor.constraint(equalTo: safeG.leadingAnchor, constant: 8.0),
scrollView.trailingAnchor.constraint(equalTo: safeG.trailingAnchor, constant: -8.0),
scrollView.bottomAnchor.constraint(equalTo: safeG.bottomAnchor, constant: -8.0),
// constrain labelOne to leading & top of Content Layout Guide with 16-pts padding
// this also defines the left & top of the scroll content
labelOne.topAnchor.constraint(equalTo: contentG.topAnchor, constant: 16.0),
labelOne.leadingAnchor.constraint(equalTo: contentG.leadingAnchor, constant: 16.0),
// constrain labelTwo leading at 400-pts from labelOne trailing
labelTwo.leadingAnchor.constraint(equalTo: labelOne.trailingAnchor, constant: 400.0),
// constrain labelTwo top at 1000-pts from the labelOne bottom
labelTwo.topAnchor.constraint(equalTo: labelOne.bottomAnchor, constant: 1000),
// constrain labelTwo to trailing & bottom of Content Layout Guide with 16-pts padding
// this also defines the right & bottom of the scroll content
labelTwo.trailingAnchor.constraint(equalTo: contentG.trailingAnchor, constant: -16.0),
labelTwo.bottomAnchor.constraint(equalTo: contentG.bottomAnchor, constant: -16.0),
])
}
}
两件事情。
1.将标签添加到滚动视图,而不是您的视图
您希望您的标签随滚动视图一起滚动,那么您不应该将它添加到您的视图中。 运行代码时,您可以滚动,但那里的固定标签固定在您的视图上,而不是在滚动视图上
2.确保你正确地添加了你的约束
在您的故事板上尝试了解哪种约束组合足以用于视图。 一个标签至少需要 4 个约束条件。
底线
这是您的代码的修改版本。 对于约束,我添加了 padding left、padding top、width 和 height,它起作用了。 我的代码是
let labelOne: UILabel = {
let label = UILabel()
label.text = "Scroll Top"
label.backgroundColor = .red
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let labelTwo: UILabel = {
let label = UILabel()
label.text = "Scroll Bottom"
label.backgroundColor = .green
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
let screensize: CGRect = UIScreen.main.bounds
let screenWidth = screensize.width
let screenHeight = screensize.height
var scrollView: UIScrollView!
scrollView = UIScrollView(frame: CGRect(x: 0, y: 120, width: screenWidth, height: screenHeight))
scrollView.addSubview(labelTwo)
NSLayoutConstraint(item: labelTwo, attribute: .leading, relatedBy: .equal, toItem: scrollView, attribute: .leadingMargin, multiplier: 1, constant: 10).isActive = true
NSLayoutConstraint(item: labelTwo, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200).isActive = true
NSLayoutConstraint(item: labelTwo, attribute: .top, relatedBy: .equal, toItem: scrollView, attribute: .topMargin, multiplier: 1, constant: 10).isActive = true
NSLayoutConstraint(item: labelTwo, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 30).isActive = true
scrollView.contentSize = CGSize(width: screenWidth, height: 2000)
view.addSubview(scrollView)
}
滚动视图看起来像这样
对我来说,这项工作很有魅力
class WithDrawConfirmationViewController: UIViewController, WithDrawConfirmationViewProtocol {
var presenter: WithDrawConfirmationPresenterProtocol?
private let viewbackgroundColor = UIColor(hexString: "#F5F5F8")
// MARK:- View properties
lazy var scrollView: UIScrollView = {
let scrollView = UIScrollView()
//view.backgroundColor = .red
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
lazy var contentView: UIView = {
let view = UIView()
//view.backgroundColor = .green
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
lazy var headerView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var titleLabel:UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = UIColor.themeBlack
label.text = "Withdraw Confirmation"//"Loading.."
label.textAlignment = .center
label.font = UIFont(name: "AvenirNext-DemiBold", size: 20)
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
return label
}()
private lazy var descriptionLabel:UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = UIColor.themeGray
label.text = "Please confirm your fixed deposit details before withdrawing your deposit"// "Loading.."
label.textAlignment = .center
label.font = UIFont(name: "AvenirNext-Medium", size: 14)
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.setContentHuggingPriority(1000, for: .vertical)
return label
}()
private lazy var instructionLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = UIColor.themeGray
label.text = "Complete fixed deposit will be withdrawn and the money will be debited to your account within 1-2 working days."//"Loading.."
label.textAlignment = .left
label.font = UIFont(name: "AvenirNext-Medium", size: 14)
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
return label
}()
private lazy var warningLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = UIColor.themeBlue
label.text = "Axis bank will levy a penalty of 1% - 2% for premature withdrawal"//"Loading.."
label.textAlignment = .left
label.font = UIFont(name: "AvenirNext-DemiBold", size: 13)
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
return label
}()
private lazy var warningView: UIView = {
let view = UIView()
view.cornerradius = 5
view.backgroundColor = UIColor(hexFromString: "#E8F4FD")
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var fdInformationDetailView: FDPurchaseDetailView = {
let view = FDPurchaseDetailView(isPoweredByViewVisible: false)
//view.backgroundColor = .red
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var footerCTAView: FooterButtonViewView = {
let view = FooterButtonViewView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
// MARK:- Life cycle
override func viewDidLoad() {
super.viewDidLoad()
contentView.backgroundColor = viewbackgroundColor
scrollView.backgroundColor = viewbackgroundColor
setUpUI()
presenter?.viewDidLoadTriggered()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
private func setUpUI() {
view.addSubview(scrollView)
scrollView.addSubview(contentView)
view.backgroundColor = viewbackgroundColor
addFooter()
setUpHeaderView()
setUpFDDetailView()
setUpInformationAndWarningView()
//scrollView.backgroundColor = .lightGray
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: footerCTAView.topAnchor).isActive = true
scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 100, right: 0)
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
contentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
//contentView.bottomAnchor.constraint(equalTo: footerCTAView.topAnchor).isActive = true
}
private func setUpHeaderView() {
contentView.addSubview(headerView)
headerView.addSubviews([titleLabel, descriptionLabel])
headerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
headerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true
headerView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4).isActive = true
titleLabel.leadingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: 8).isActive = true
titleLabel.trailingAnchor.constraint(equalTo: headerView.trailingAnchor).isActive = true
titleLabel.topAnchor.constraint(equalTo: headerView.topAnchor, constant: 8).isActive = true
descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20).isActive = true
descriptionLabel.leadingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: 8).isActive = true
descriptionLabel.trailingAnchor.constraint(equalTo: headerView.trailingAnchor).isActive = true
descriptionLabel.bottomAnchor.constraint(equalTo: headerView.bottomAnchor, constant: -20).isActive = true
}
private func setUpFDDetailView() {
contentView.addSubview(fdInformationDetailView)
fdInformationDetailView.topAnchor.constraint(equalTo: headerView.bottomAnchor).isActive = true
fdInformationDetailView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
fdInformationDetailView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true
}
private func setUpInformationAndWarningView() {
contentView.addSubview(instructionLabel)
instructionLabel.topAnchor.constraint(equalTo: fdInformationDetailView.bottomAnchor, constant: 20).isActive = true
instructionLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
instructionLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true
warningView.addSubview(warningLabel)
warningLabel.topAnchor.constraint(equalTo: warningView.topAnchor, constant: 8).isActive = true
warningLabel.leadingAnchor.constraint(equalTo: warningView.leadingAnchor, constant: 20).isActive = true
warningLabel.trailingAnchor.constraint(equalTo: warningView.trailingAnchor, constant: -20).isActive = true
warningLabel.bottomAnchor.constraint(equalTo: warningView.bottomAnchor, constant: -8).isActive = true
contentView.addSubview(warningView)
warningView.topAnchor.constraint(equalTo: instructionLabel.bottomAnchor, constant: 8).isActive = true
warningView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
warningView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20).isActive = true
//warningView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
warningView.bottomAnchor.constraint(greaterThanOrEqualTo: contentView.bottomAnchor, constant: -20).isActive = true
}
private func addFooter() {
view.addSubview(footerCTAView)
footerCTAView.delegate = self
footerCTAView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
footerCTAView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
footerCTAView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
}
将滚动视图图像设置为墙纸:
@IBOutlet var scroll_view_img: UIScrollView!
var itemPhotoList = NSMutableArray()
var button = NSMutableArray()
@IBOutlet var imageview_big: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
itemPhotoList = ["grief-and-loss copy.jpg","aaa.jpg","image_4.jpeg"]
// button = ["btn1","btn2"]
let width:CGFloat = 100
let height:CGFloat = 100
var xposition:CGFloat = 10
var scroll_contont:CGFloat = 0
for i in 0 ..< itemPhotoList.count
{
var button_img = UIButton()
button_img = UIButton(frame: CGRect(x: xposition, y: 50, width: width, height: height))
let img = UIImage(named:itemPhotoList[i] as! String)
button_img.setImage(img, for: .normal)
scroll_view_img.addSubview(button_img)
button_img.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
button_img.tag = i
view.addSubview(scroll_view_img)
xposition += width+10
scroll_contont += width
scroll_view_img.contentSize = CGSize(width: scroll_contont, height: height)
}
}
func buttonAction(sender: UIButton!)
{
switch sender.tag {
case 0:
imageview_big.image = UIImage(named: "grief-and-loss copy.jpg")
case 1:
imageview_big.image = UIImage(named: "aaa.jpg")
case 2:
imageview_big.image = UIImage(named: "image_4.jpeg")
default:
break
}
}
将此控制器复制并粘贴到您的项目中
class BaseScrollViewController: UIViewController {
lazy var contentViewSize = CGSize(width: self.view.frame.width, height: self.view.frame.height + 100)
lazy var scrollView: UIScrollView = {
let view = UIScrollView(frame: .zero)
view.backgroundColor = .white
view.frame = self.view.bounds
view.contentSize = contentViewSize
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
lazy var containerView: UIView = {
let v = UIView()
v.backgroundColor = .white
v.frame.size = contentViewSize
return v
}()
override func viewDidLoad() {
view.backgroundColor = .white
view.addSubview(scrollView)
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
scrollView.addSubview(containerView)
setupContainer(containerView)
super.viewDidLoad()
}
public func setupContainer(_ container: UIView) {
}
}
以上代码的用法:
class ClientViewController: BaseScrollViewController {
override func viewDidLoad() {
super.viewDidLoad()
// do your stuff here
}
override func setupContainer(_ container: UIView) {
// add views here
}
}
这些答案不适用于导航栏中的大标题。 确保在视图控制器的 viewDidLoad() 方法中包含以下代码:
self.navigationController?.navigationBar.prefersLargeTitles = false
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.