ViewControlling full of textEdits not scrolling down with scrollview - swift

I have a view controller with 8 to 9 textEdits where user has to fill them out to save to a database but it is taking a lot of my screen and some TE is not being shown because of the size of the iphones screen.I then decide to add a UIScrollView like this :
lazy var myScrollView : UIScrollView = {
let scrol = UIScrollView()
scrol.contentSize.height = 10000
scrol.backgroundColor = appBackgroundColor
scrol.translatesAutoresizingMaskIntoConstraints = false
return scrol
}()
...
view.addSubview(myScrollView)
myScrollView.addSubview(labelYear)
myScrollView.addSubview(labelAppTitle)
// then I added the constraints
NSLayoutConstraint.activate([
myScrollView.topAnchor.constraint(equalTo: view.topAnchor),
myScrollView.leftAnchor.constraint(equalTo: view.leftAnchor),
myScrollView.rightAnchor.constraint(equalTo: view.rightAnchor),
//enter code here
myScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
labelAppTitle.leftAnchor.constraint(equalTo: myScrollView.leftAnchor,constant: 40),
labelAppTitle.topAnchor.constraint(equalTo: myScrollView.safeAreaLayoutGuide.topAnchor, constant: 10),
labelAppTitle.rightAnchor.constraint(equalTo:myScrollView.rightAnchor, constant: -40),
labelAppTitle.heightAnchor.constraint(equalToConstant: 90)
])
I have a lot more textEdits but I am not posting for sake of saving space.The problem is that it is not scrolling down like I wanted . How do I do this?
thank you

import UIKit
class TestController: UIViewController, UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
initUI()
}
func initUI() {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.isUserInteractionEnabled = true
view.addSubview(scrollView)
let contentView = UIView()
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.isUserInteractionEnabled = true
contentView.isMultipleTouchEnabled = true
scrollView.addSubview(contentView)
let titleText = UITextField(frame: CGRect.zero)
titleText.translatesAutoresizingMaskIntoConstraints = false
titleText.borderStyle = .roundedRect
titleText.isEnabled = true
titleText.isUserInteractionEnabled = true
titleText.placeholder = "Constants.Messages.titlePlaceholder"
titleText.isUserInteractionEnabled = true
titleText.delegate = self
contentView.addSubview(titleText)
// scroll view
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8.0),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -8.0),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0)
])
// content view
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
])
// title text field
NSLayoutConstraint.activate([
titleText.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20.0),
titleText.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0),
titleText.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8.0),
titleText.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0)
])
}
}
This is an exmaple of using scrollView. When you create a scrollView, apple recommends to put a contentView in it and put it inside in scrollView and don't forget to use bottomAnchor. If you forgot to use that then it'll not scroll.

Related

UITextFields keyboard not appearing in UIScrollview

I have 2 textfields as subViews of a contentView and the contentView is a subView of a scrollView. The textfields appear with no issue.But the problem I am having is when I tap or select the textfield to enter text neither a keyboard appears or the blue cursor, the textfields placeholder remains there. Is there something wrong with my constraints? How can I get the keyboard to appear and edit the text?
class SignInViewController: UIViewController {
private let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
private let contentView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let emailOrPhoneTextField: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = "Email or Phone Number"
textField.textAlignment = .center
textField.backgroundColor = .red
return textField
}()
private let passwordTextField: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = "Password"
textField.backgroundColor = .yellow
return textField
}()
override func viewDidLoad() {
super.viewDidLoad()
setupScrollView()
setupTextFields()
}
}
extension SignInViewController{
private func setupScrollView(){
view.addSubview(scrollView)
scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
scrollView.addSubview(contentView)
contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
}
private func setupTextFields(){
contentView.addSubview(emailOrPhoneTextField)
contentView.addSubview(passwordTextField)
emailOrPhoneTextField.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
emailOrPhoneTextField.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 25).isActive = true
emailOrPhoneTextField.widthAnchor.constraint(equalTo: contentView.widthAnchor).isActive = true
emailOrPhoneTextField.heightAnchor.constraint(equalToConstant: 44).isActive = true
passwordTextField.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
passwordTextField.topAnchor.constraint(equalTo: emailOrPhoneTextField.bottomAnchor, constant: 25).isActive = true
passwordTextField.widthAnchor.constraint(equalTo: contentView.widthAnchor).isActive = true
passwordTextField.heightAnchor.constraint(equalToConstant: 44).isActive = true
}
}
Try this and check if it works:
extension ViewController{
private func setupScrollView(){
view.addSubview(scrollView)
scrollView.addSubview(contentView)
contentView.addSubview(emailOrPhoneTextField)
contentView.addSubview(passwordTextField)
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor)
])
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.rightAnchor.constraint(equalTo: scrollView.rightAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
contentView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
contentView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
])
NSLayoutConstraint.activate([
emailOrPhoneTextField.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 50),
emailOrPhoneTextField.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
emailOrPhoneTextField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
])
NSLayoutConstraint.activate([
passwordTextField.topAnchor.constraint(equalTo: emailOrPhoneTextField.bottomAnchor, constant: 25),
passwordTextField.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
passwordTextField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
])
}
}

UIStackvView jumping in the UIScrollView. Swift

I understand that this is most likely a matter of limitations. But when I set the width to the view it still doesn't help me.
I find similar questions. But they don't solve my problem.
How to get rid of this?
lazy var scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.backgroundColor = .white
scrollView.addSubview(stackView)
scrollView.showsVerticalScrollIndicator = false
scrollView.showsHorizontalScrollIndicator = false
scrollView.alwaysBounceHorizontal = false
return scrollView
}()
private func setupScrollViewConstraint() {
let frameLayoutGuide = scrollView.frameLayoutGuide
NSLayoutConstraint.activate([
frameLayoutGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor),
frameLayoutGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor),
frameLayoutGuide.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
frameLayoutGuide.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
frameLayoutGuide.widthAnchor.constraint(equalTo: view.widthAnchor)
])
}
private func setupStackViewConstraint() {
let contentLayoutGuide = scrollView.contentLayoutGuide
NSLayoutConstraint.activate([
stackView.leadingAnchor.constraint(equalTo: contentLayoutGuide.leadingAnchor, constant: 5),
stackView.trailingAnchor.constraint(equalTo: contentLayoutGuide.trailingAnchor, constant: -5),
stackView.topAnchor.constraint(equalTo: contentLayoutGuide.topAnchor, constant: 5),
stackView.bottomAnchor.constraint(equalTo: contentLayoutGuide.bottomAnchor, constant: -5)])
}
It is necessary to fix in the center the stack that is in the scroll view.
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor)

How to programmatically pin a UIImageView

I read the documentation, but I just can't figure out what exactly is needed in my simple case.
The element is constantly jumping. I need just that.
I would be grateful for articles and so on. For a deeper understanding of this
class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white
let imageView = UIImageView()
view.addSubview(imageView)
self.view = view
}
}
You are looking for auto layout constraints.
E.g. add to your code:
imageView.translatesAutoresizingMaskIntoConstraints = false
// add desired constraints here.
imageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
...
You may want to set top, leading and trailing anchors, depending on the desired behavior.
imageView.translatesAutoresizingMaskIntoConstraints = false
// Apply constraint
NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 10),
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: 1)
])

Creating scrollview with 20 labels with programmatically in Swift

I am pretty new in Programming Swift so I am trying to achieve a scrollable task includes 20 labels inside. I made it with storyboard but programmatically I failed..
Thanks in advance, a green view background and 20 labels orange. Can anyone show me how ?
So i am not very fond of advertising, but raywenderlich has an awesome tutorial on how to do this. It is quite easy, but it comes down to a scrollable view and a tableview with navigation links.
https://www.raywenderlich.com/5662524-your-second-ios-and-swiftui-app
Again, i am not advertising, just sharing some videos that really helped me understand Swift!
And for answering your question:
Use
Scrollview { put here your to-do code
} end of body
There is your scrollable view with all the labels!
Below code will print your label 20 times with scrollview.
import UIKit
class ViewController: UIViewController {
let scrollView = UIScrollView()
var a = 0
var COnstant: CGFloat = 20
override func viewDidLoad() {
super.viewDidLoad()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.backgroundColor = .green
self.view.addSubview(scrollView)
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
while a<20 {
let label = UILabel()
label.backgroundColor = .orange
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = .black
label.text = "I'm label \(a)"
label.textAlignment = .center
scrollView.addSubview(label)
label.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 0).isActive = true
label.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 0).isActive = true
label.widthAnchor.constraint(equalTo: scrollView.widthAnchor, constant: 0).isActive = true
label.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: COnstant).isActive = true
COnstant += 40
a = a+1
if a >= 20 { // if bottomanchor is not set then our scroll view doesnot work
label.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0).isActive = true
}
}
}
}

How to resize content view in UIScrollView programmatically?

Here is the issue: I need to add a view containing other subviews to a scroll view programmatically. In addition, I also need to make the frame of such a view to stick to the bounds of the main super view. The code below shows the approach I was trying to implement, but as you can see from the pictures below the 'contentView' is not updating its frame size when the screen is rotated. The initial code is taken from here for demonstration purposes. Any help would be greatly appreciated.
import UIKit
class TestViewController : UIViewController {
var contentViewSize = CGSize()
let contentView: UIView = {
let view = UIView()
view.backgroundColor = .magenta
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
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 viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
contentViewSize = view.bounds.size
labelTwo.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: (contentViewSize.width - labelTwo.frame.size.width - 16.0)).isActive = true
labelTwo.topAnchor.constraint(equalTo: contentView.topAnchor, constant: (contentViewSize.height - labelTwo.frame.size.height - 16.0)).isActive = true
}
override func viewDidLoad() {
super.viewDidLoad()
contentViewSize = view.bounds.size
view.backgroundColor = .yellow
self.view.addSubview(scrollView)
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
scrollView.addSubview(contentView)
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 16).isActive = true
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 16).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 16).isActive = true
contentView.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 16).isActive = true
contentView.addSubview(labelOne)
labelOne.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16.0).isActive = true
labelOne.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16.0).isActive = true
contentView.addSubview(labelTwo)
labelTwo.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: (contentViewSize.width - labelTwo.frame.size.width - 16.0)).isActive = true
labelTwo.topAnchor.constraint(equalTo: contentView.topAnchor, constant: (contentViewSize.height - labelTwo.frame.size.height - 16.0)).isActive = true
labelTwo.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -16.0).isActive = true
labelTwo.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -16.0).isActive = true
}
}
You made some odd changes to the code from the answer you linked to. Also, that answer is a little out-of-date.
Here's a better example. Assuming you want only vertical scrolling, this will:
add a Cyan scroll view, inset 8-pts on each side from the safe-area
add a Magenta "content view" to the scroll view, with 16-pts on each side constrained to the scroll view's contentLayoutGuide, with a width 32-pts less than the scroll view's frame (16-pts on each side)
add a label at top-left of the content view
add a label at bottom-right of the content view
constrain the bottom label 1500-pts below the top label (so it will scroll vertically)
Code:
class ScrollTestViewController : UIViewController {
let contentView: UIView = {
let view = UIView()
view.backgroundColor = .magenta
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
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()
view.backgroundColor = .yellow
// add the scroll view
self.view.addSubview(scrollView)
// add contentView to scroll view
scrollView.addSubview(contentView)
// add two labels to contentView
contentView.addSubview(labelOne)
contentView.addSubview(labelTwo)
// respect safe-area
let g = view.safeAreaLayoutGuide
// if you want to ignore the safe-area (bad idea),
// use this instead
//let g = view!
//scrollView.contentInsetAdjustmentBehavior = .never
// we're going to constrain the contentView to the scroll view's content layout guide
let scg = scrollView.contentLayoutGuide
NSLayoutConstraint.activate([
// constrain scrollView Top / Leading / Trailing / Bottom to view (safe-area)
// with 8-pts on each side
scrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0),
// constrain contentView Top / Leading / Trailing / Bottom to scroll view's Content Layout Guide
// with 16-pts on each side
contentView.topAnchor.constraint(equalTo: scg.topAnchor, constant: 16.0),
contentView.leadingAnchor.constraint(equalTo: scg.leadingAnchor, constant: 16.0),
contentView.trailingAnchor.constraint(equalTo: scg.trailingAnchor, constant: -16.0),
contentView.bottomAnchor.constraint(equalTo: scg.bottomAnchor, constant: -16.0),
// if we only want vertical scrolling, constrain contentView Width
// to scrollView's Frame Layout Guide minus 32-pts (because we have 16-pts on each side)
contentView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor, constant: -32.0),
// constrain labelOne Top / Leading 16-pts to contentView Top / Leading
// (so it shows up at top-left corner)
labelOne.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16.0),
labelOne.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16.0),
// constrain labelTwo Bottom / Trailing 16-pts to contentView Bottom / Trailing
// (so it shows up at bottom-right corner)
labelTwo.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16.0),
labelTwo.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -16.0),
// constrain labelTwo Top to labelOne Bottom + 1500-pts
// so we'll have some vertical scrolling to get to it
labelTwo.topAnchor.constraint(equalTo: labelOne.bottomAnchor, constant: 1500.0),
])
}
}