Search code examples
iosswiftuiviewpure-layout

Using scroll view programmatically


I am trying to develop an app with the UI created only programmatically. I want to create a simple view which is a UIScrollView (to be able to scroll the view when the keyboard is appearing) with a containerView (UIView) where we can find a button.

I am using PureLayout to make easier the set up of constraints, swift 4, Xcode 9.2 beta

Below the class of this view

class SimpleView: UIScrollView {

var containerView: UIView!
var signInButton: UIButton!
var signInLabel: UILabel!

var screenSize: CGSize = CGSize.zero

var shouldSetupConstraints = true

override init(frame: CGRect) {
    super.init(frame: frame)

    self.screenSize = frame.size

    self.containerView = UIView(frame: CGRect.zero)
    self.signInButton = UIButton(frame: CGRect.zero)
    self.signInLabel = UILabel(frame: CGRect.zero)

    self.addSubview(self.containerView)

    self.containerView.addSubview(self.signInButton)

    self.signInButton.addSubview(self.signInLabel)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override func updateConstraints() {
    if(shouldSetupConstraints) {

        self.layoutSignInButton()
        self.layoutSignInLabel()

        shouldSetupConstraints = false
    }
    super.updateConstraints()


}


private func layoutContainerView() {
    self.containerView.autoPinEdgesToSuperviewEdges()
    self.containerView.backgroundColor = UIColor.yellow
}

private func layoutSignInButton() {
    self.signInButton.autoPinEdge(toSuperviewEdge: .right)
    self.signInButton.autoPinEdge(toSuperviewEdge: .left)
    self.signInButton.autoPinEdge(toSuperviewEdge: .top)
    self.signInButton.autoSetDimension(.height, toSize: 55.0)

    self.signInButton.backgroundColor = UIColor(hex: "#FD9FA2")
}

private func layoutSignInLabel() {
    self.signInLabel.autoPinEdgesToSuperviewEdges()

    self.signInLabel.shadowColor = UIColor(hex: "#9A615E")
    self.signInLabel.shadowOffset = CGSize(width: 0.0, height: 2)
    self.signInLabel.text = NSLocalizedString("SIGN IN", comment: "")
    self.signInLabel.textAlignment = .center
    self.signInLabel.textColor = UIColor.white
    self.signInLabel.font = UIFont.boldSystemFont(ofSize: 15.0)
    self.signInLabel.backgroundColor = UIColor.clear
}

}

Below the code of the UIViewController subclass embedding the previous view

class SignInViewController: UIViewController {

var simpleView: SimpleView!

override func viewDidLoad() {
    super.viewDidLoad()

    self.simpleView = SimpleView(frame: self.view.bounds) // with SimpleView(frame: self.view.frame) has the same behaviour
    self.view.addSubview(self.simpleView)

    self.simpleView.autoPinEdgesToSuperviewEdges()
    self.navigationController?.navigationBar.isHidden = true

}
}

Unfortunatly the result is not the one expected : see below

What am I missing ? Different points are missing: - The position of the button is weird (space between the button and the top / left side of the button partly hidden outside of the screen) - the container view is invisible (backgroundColor = UIColor.yellow has no effect)

Thank you by advance !

//////////////////////////// EDIT ////////////////////////////////

Below a screenshot of the exact same code using a UIView instead of UIScrollView

Class SimpleView: UIView {

enter image description here


Solution

  • The content of a UIScrollView must also define the .contentSize` of the scroll view.

    I don't use PureLayout, so I don't know what the syntax is, but in your layoutContainerView() func, you need to also do:

    self.containerView ... set width dimension to SuperviewWdith
    

    That will set the content of containerView to the width of the scroll view, and that should fix the width part.

    I assume you will be adding elements to containerView and set their constraints to control the height of it.