scrollview programmatically initial position swift 4 - ios

I have a scroll view, with some text that, however, when I access the view it displays me in half, I would like to see the text starting from above..
my main problem is that I do not see the scrollview from the initial position, but it starts from the bottom
please someone can help me?
import Foundation
import AVFoundation
import UIKit
class ArTestoController: UIView, UIScrollViewDelegate {
var scrollView = UIScrollView().then {
$0.alpha = 1
$0.contentMode = .scaleToFill
//$0.contentOffset = CGPoint(x:30.0, y:30.0)
//$0.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}
let text = UITextView().then {
$0.text =
"""
1. Introduzione alla Chiesa di Santa Maria delle Grazie
2. Crocifissione
3. Pilato si lava le mani
"""
$0.textColor = .white
$0.textAlignment = .left
$0.backgroundColor = UIColor.clear
$0.font = UIFont(name: "Raleway-Medium", size: 15)
$0.sizeToFit()
$0.isEditable = false
$0.isUserInteractionEnabled = true
$0.isSelectable = false
}
func setText() {
}
func showOperaImage(){
self.addSubview(scrollView)
self.scrollView.addSubview(text)
scrollView.activate([
scrollView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
scrollView.centerYAnchor.constraint(equalTo: self.centerYAnchor),
scrollView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1),
scrollView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1),
])
text.activate([
text.centerXAnchor.constraint(equalTo: self.scrollView.centerXAnchor),
text.topAnchor.constraint(equalTo: self.scrollView.topAnchor, constant: 10),
text.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.9),
text.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.9),
text.bottomAnchor.constraint(equalTo: self.scrollView.bottomAnchor, constant: -28),
text.leadingAnchor.constraint(equalTo: self.scrollView.leadingAnchor, constant: 5),
text.trailingAnchor.constraint(equalTo: self.scrollView.trailingAnchor),
])
scrollView.backgroundColor = UIColor.black
}
func activateView() {
self.scrollView = UIScrollView()
self.scrollView.delegate = self
showOperaImage()
setText()
}
}
this not work:
self.testoView.scrollView.contentOffset = (CGPoint(x: 0, y: 0), animated: true)

Related

Need to add Label on UIView programatically based on some conditions using swift

I am working on a canvas view where I am trying to add image to a UIView and a text to a UIView, on satisfying some conditions.
The issue is, I am not able to add label to my UIView after satisfying the required condition. I tried this code separately without any functions and conditions and it is working fine. But if I try and run it as given below it doesn't show me the label on the UIView.
[Note- The code here is working fine for imageView.]
I tried various constraint combinations like, centerX, centerY, width, height or leading, trailing, top, bottom. But nothing is working. Please help.
My code is as below: -
class CanvasViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
createCanvasOnAspectRatio()
}
func createCanvasOnAspectRatio() {
let View1: UIView = {
let viewView = UIView()
viewView.translatesAutoresizingMaskIntoConstraints = false
viewView.contentMode = .scaleAspectFit
print(UserDefaults.standard.bool(forKey: "backgroundColourSelected"))
if UserDefaults.standard.bool(forKey: "backgroundColourSelected") {
viewView.backgroundColor = self.viewColor
}else {
viewView.backgroundColor = .white
}
viewView.clipsToBounds = true
return viewView
}()
self.canvasView.addSubview(View1)
View1.centerXAnchor.constraint(equalTo: canvasView.centerXAnchor, constant: 0).isActive = true
View1.centerYAnchor.constraint(equalTo: canvasView.centerYAnchor, constant: 0).isActive = true
View1.widthAnchor.constraint(equalTo: canvasView.widthAnchor, constant: 0).isActive = true
View1.heightAnchor.constraint(equalTo: canvasView.widthAnchor, multiplier: aspectRatio).isActive = true
if UserDefaults.standard.bool(forKey: "imageSelectedFromGallexy") == true {
for item in 0..<self.imagesForGallery.count {
let image = imagesForGallery[item]
let image_View: UIImageView = {
let imageV = UIImageView()
imageV.image = image
imageV.contentMode = .scaleAspectFill
imageV.translatesAutoresizingMaskIntoConstraints = false
imageV.clipsToBounds = true
return imageV
}()
View1.addSubview(image_View)
image_View.topAnchor.constraint(equalTo: View1.topAnchor, constant: 0).isActive = true
image_View.bottomAnchor.constraint(equalTo: View1.bottomAnchor, constant: 0).isActive = true
image_View.leadingAnchor.constraint(equalTo: View1.leadingAnchor, constant: 0).isActive = true
image_View.trailingAnchor.constraint(equalTo: View1.trailingAnchor, constant: 0).isActive = true
}
}
if UserDefaults.standard.bool(forKey: "addTextToCanvas") == true {
let labelTextView: UILabel = {
let labelView = UILabel()
//labelView.frame = CGRect(x: 0.0, y: 0.0, width: 50.0, height: 30.0)
labelView.translatesAutoresizingMaskIntoConstraints = false
labelView.textColor = .green
labelView.text = "Hello"
labelView.font = UIFont(name: "Avenir-Medium", size: 15.0)
labelView.textAlignment = .center
// labelView.clipsToBounds = true
return labelView
}()
View1.addSubview(labelTextView)
labelTextView.centerXAnchor.constraint(equalTo: View1.centerXAnchor, constant: 0).isActive = true
labelTextView.centerYAnchor.constraint(equalTo: View1.centerYAnchor, constant: 0).isActive = true
labelTextView.widthAnchor.constraint(equalTo: View1.widthAnchor, constant: 0).isActive = true
labelTextView.heightAnchor.constraint(equalTo: View1.widthAnchor, multiplier: 1.0).isActive = true
UserDefaults.standard.set(false, forKey: "addTextToCanvas")
}
}
}

Get offset when Scrollview is animated

I have a scorll view with animating
UIView.animate(withDuration: Double(totalMidiTime) / 1000, delay: 0, options: .curveLinear) {
self.scrollView.contentOffset.x = self.scrollView.contentSize.width - self.leftMargin
} completion: { (_) in }
I want to get current postion offset when it's animating
You can get the offset by checking the bounds.origin.x value of the scroll view's presentation layer:
guard let pl = scrollView.layer.presentation() else {
return
}
print("Content Offset X:", pl.bounds.origin.x)
Here's a complete example...
We create a scroll view with 30 labels. On viewDidAppear we start a 20-second horizontal animation to the last label. Each time we tap the button, the "status label" will update with the current bounds.origin.x of the scroll view's presentation layer (which matches the contentOffset.x):
class ViewController: UIViewController {
let scrollView: UIScrollView = {
let v = UIScrollView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .systemGreen
return v
}()
let testButton: UIButton = {
let v = UIButton()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .blue
v.setTitle("Get Offset", for: [])
v.setTitleColor(.lightGray, for: .highlighted)
return v
}()
let statusLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.numberOfLines = 0
v.textAlignment = .center
v.text = "Content Offset X\n0.00"
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
let stack = UIStackView()
stack.distribution = .fillEqually
stack.spacing = 8
stack.translatesAutoresizingMaskIntoConstraints = false
for i in 1...30 {
let v = UILabel()
v.backgroundColor = .yellow
v.text = "Label \(i)"
v.textAlignment = .center
stack.addArrangedSubview(v)
}
scrollView.addSubview(stack)
view.addSubview(scrollView)
view.addSubview(testButton)
view.addSubview(statusLabel)
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.heightAnchor.constraint(equalToConstant: 60.0),
stack.topAnchor.constraint(equalTo: cg.topAnchor, constant: 8.0),
stack.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 8.0),
stack.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: -8.0),
stack.bottomAnchor.constraint(equalTo: cg.bottomAnchor),
stack.heightAnchor.constraint(equalTo: fg.heightAnchor, constant: -16.0),
testButton.topAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 20.0),
testButton.centerXAnchor.constraint(equalTo: g.centerXAnchor),
testButton.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.6),
statusLabel.topAnchor.constraint(equalTo: testButton.bottomAnchor, constant: 20.0),
statusLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
statusLabel.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.9),
])
testButton.addTarget(self, action: #selector(gotTap(_:)), for: .touchUpInside)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 20.0, delay: 0, options: .curveLinear) {
self.scrollView.contentOffset.x = self.scrollView.contentSize.width - self.scrollView.frame.width
} completion: { (_) in }
}
#objc func gotTap(_ sender: UIButton) -> Void {
guard let pl = scrollView.layer.presentation() else {
return
}
let x = String(format: "%0.2f", pl.bounds.origin.x)
statusLabel.text = "Content Offset X\n\(x)"
}
}

Simple slide up animation on UIView using NSLayoutConstraints

I have spent a while trying to figure this out, but I just can't. There is probably something really simple I am missing here. I am trying to animate a view coming in from the bottom. This si the code I am using for the view:
private let undoView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .white
view.layer.cornerRadius = 15
view.layer.shadowOffset = .zero
view.layer.shadowOpacity = 0.3
view.layer.shadowRadius = 5
view.layer.shouldRasterize = true
view.layer.rasterizationScale = UIScreen.main.scale
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Undo", for: .normal)
button.titleLabel?.textAlignment = .center
button.setTitleColor(.systemBlue, for: .normal)
let buttonConstraints = [
button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
button.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
button.topAnchor.constraint(equalTo: view.topAnchor, constant: 16),
button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -16)
]
view.addSubview(button)
NSLayoutConstraint.activate(buttonConstraints)
let swipeGesture = UISwipeGestureRecognizer(target: view, action: #selector(undoViewSwiped))
view.addGestureRecognizer(swipeGesture)
return view
}()
And this is the code I am using to try and achieve the animation:
func addUndoView() {
var bottomConstraint = undoView.topAnchor.constraint(equalTo: view.bottomAnchor, constant: 0)
let constraints = [
undoView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
undoView.widthAnchor.constraint(equalToConstant: view.bounds.width / 3),
bottomConstraint,
undoView.heightAnchor.constraint(equalToConstant: 50)
]
view.addSubview(undoView)
NSLayoutConstraint.activate(constraints)
undoView.layoutIfNeeded()
bottomConstraint.isActive = false
bottomConstraint = undoView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor, constant: -58)
bottomConstraint.isActive = true
UIView.animate(withDuration: 0.5, delay: 0.2, animations: {
self.undoView.layoutIfNeeded()
})
}
I want the view to just be created underneath the visible view, and then slide up to 8 above the bottom layout margin. This code however just makes the view 'expand' at its final position instead of coming into view from the bottom. Using self.view.layoutIfNeeded() makes the view fly in from the top left of the screen, for some reason.
good day I usually work with transform property for move one view from x position to y portion, please check this example.
class ViewController: UIViewController {
let button : UIButton = {
let button = UIButton(type: .custom)
button.setTitle("Button", for: .normal)
button.backgroundColor = .gray
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let customView : UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .red
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(button)
view.addSubview(customView)
NSLayoutConstraint.activate([
button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
customView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
customView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
customView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
customView.heightAnchor.constraint(equalToConstant: 100)
])
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
setupAnimationCustomView()
}
private func setupAnimationCustomView(){
UIView.animate(withDuration: 1, delay: 0 , options: .curveEaseOut, animations: {
print(self.button.frame.origin.y)
let translationY = self.view.frame.height - self.button.frame.origin.y - self.button.frame.height - self.customView.frame.height - 8
self.customView.transform = CGAffineTransform(translationX: 0, y: translationY * (-1))
}, completion: nil)
}
}
on the animation I calculate the distance that I need to move my customView.

correct layer swift programmatically

As you can see from the picture, despite the "masksToBounds" I see the layer under the botton x. How can I solve?
class StickerView: UIImageView {
let stickerIdentifier: String
let xButton = UIButton().then {
$0.setImage(Asset.delete_sticker.image.withRenderingMode(.alwaysOriginal), for: .normal)
$0.layer.cornerRadius = 30/2
$0.imageView?.contentMode = .scaleAspectFit
$0.layer.masksToBounds = true
$0.alpha = 1
$0.translatesAutoresizingMaskIntoConstraints = true
}
init(frame: CGRect, name: String) {
self.stickerIdentifier = "\(name.replacingOccurrences(of: ".png", with: ""))"
super.init(frame: frame)
setLayout()
}
func setLayout() {
self.addSubview(xButton)
self.bringSubviewToFront(xButton)
self.xButton.activate([
self.xButton.topAnchor.constraint(equalTo: self.topAnchor, constant: -10),
self.xButton.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 10),
self.xButton.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.15),
self.xButton.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.15),
])
}

Using ScrollView Programmatically in Swift 3

I have searched other questions and seem to still have some trouble creating my scrollView programmatically with autolayout in swift 3. I am able to get my scrollview to show up as shown in the picture below, but when I scroll to the bottom my other label does not show up and the 'scroll top' label does not disappear.
Hoping someone can help review my code below!
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)
}
}
It is easy to use constraints to define the scroll content size - so you don't have to do any manual calculations.
Just remember:
The content elements of your scroll view must have left / top / width / height values. In the case of objects such as labels, they have intrinsic sizes, so you only have to define the left & top.
The content elements of your scroll view also define the bounds of the scrollable area - the contentSize - but they do so with the bottom & right constraints.
Combining those two concepts, you see that you need a "continuous chain" with at least one element defining the top / left / bottom / right extents.
Here is a simple example, that will run directly in a Playground page:
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
Edit - since this answer still gets occasional attention, I've updated the code to use more modern syntax, to respect the safe-area, and to use the scroll view's .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),
])
}
}
Two things.
1. Add the labels to scroll view, not your view
You want your label to scroll with scroll view, then you should not add it on your view. When running your code, you can scroll but the fixed label there is pinned to your view, not on your scroll view
2. Make sure you added your constraints correctly
Try it on your storyboard about what combination of constraint is enough for a view. At least 4 constraints are needed for a label.
Bottom line
Here is a modified version of your code. For constraint I added padding left, padding top, width and height and it works. My code is
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)
}
And the scroll view looks like this
For me this work like charm
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
}
}
Set scrollview images to the wallpaper:
#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
}
}
Copy and paste this controller in your project
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) {
}
}
Usage for above code:
class ClientViewController: BaseScrollViewController {
override func viewDidLoad() {
super.viewDidLoad()
// do your stuff here
}
override func setupContainer(_ container: UIView) {
// add views here
}
}
These answers do not work with large titles in the navigation bar. Make sure you have the code below in your viewDidLoad() method of your view controller:
self.navigationController?.navigationBar.prefersLargeTitles = false

Resources