I have a stack view that is programmatically inserted inside a scroll view (which is working perfectly) but when I put the scroll view inside the view controller in a storyboard the alignment is .fill and the distribution of the component is not applicable through UI. Then I coded it as below but it still didn't work.
Below is the code of programmatic implementation:
class RegisterVC: UIViewController{
private let dataSource = ["Student","Academic Staff","Non academic Staff"]
#IBOutlet weak var userPicker: UIPickerView!
#IBOutlet weak var FirstName: UITextField!
#IBOutlet weak var LastName: UITextField!
#IBOutlet weak var EmailAddress: UITextField!
#IBOutlet weak var Password: UITextField!
//message popping validator labels
#IBOutlet weak var firstNameLabel: UILabel!
#IBOutlet weak var lastNameLabel: UILabel!
#IBOutlet weak var emailAddressLabel: UILabel!
#IBOutlet weak var passwordLabel: UILabel!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet var formStackView: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.translatesAutoresizingMaskIntoConstraints = false;
self.scrollView.addSubview(formStackView)
self.formStackView.translatesAutoresizingMaskIntoConstraints=false
self.formStackView.alignment = .fill
self.formStackView.distribution = .fillProportionally
self.formStackView.leadingAnchor.constraint(equalTo: self.scrollView.leadingAnchor,constant: 20).isActive=true
self.formStackView.trailingAnchor.constraint(equalTo: self.scrollView.trailingAnchor,constant: 20).isActive=true
self.formStackView.topAnchor.constraint(equalTo: self.scrollView.topAnchor,constant: 50).isActive=true
self.formStackView.bottomAnchor.constraint(equalTo: self.scrollView.bottomAnchor).isActive=true
//self.formStackView.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive=true
userPicker.delegate=self
userPicker.dataSource=self
}
}
I'm a very basic beginner in iOS; I need your dire help, thank you.
That's an unusual way of designing in Storyboard... you can layout your stack view directly as a subview of your scroll view, and set up the constraints there (instead of via code).
But, I'll assume you have a reason for doing it that way, so...
You want to constrain the stack view's Top / Leading / Trailing / Bottom constraints to the scroll view's Content Layout Guide ... and then constrain its Width to the scroll view's Frame Layout Guide.
Try it like this:
class RegisterVC: UIViewController {
private let dataSource = ["Student","Academic Staff","Non academic Staff"]
#IBOutlet weak var userPicker: UIPickerView!
#IBOutlet weak var FirstName: UITextField!
#IBOutlet weak var LastName: UITextField!
#IBOutlet weak var EmailAddress: UITextField!
#IBOutlet weak var Password: UITextField!
//message popping validator labels
#IBOutlet weak var firstNameLabel: UILabel!
#IBOutlet weak var lastNameLabel: UILabel!
#IBOutlet weak var emailAddressLabel: UILabel!
#IBOutlet weak var passwordLabel: UILabel!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet var formStackView: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
// not needed...
//scrollView.translatesAutoresizingMaskIntoConstraints = false;
// add form stack view to the scroll view
scrollView.addSubview(formStackView)
// because of the way this is designed in Storyboard,
// we need to set this to false
formStackView.translatesAutoresizingMaskIntoConstraints = false
// stack view alignment .fill
formStackView.alignment = .fill
// stack view distribution should be .fill
formStackView.distribution = .fill // .fillProportionally
// we want to constrain the stack view to the scroll view's Content Layout Guide
let svCLG = scrollView.contentLayoutGuide
NSLayoutConstraint.activate([
formStackView.leadingAnchor.constraint(equalTo: svCLG.leadingAnchor, constant: 20),
formStackView.trailingAnchor.constraint(equalTo: svCLG.trailingAnchor, constant: 20),
formStackView.topAnchor.constraint(equalTo: svCLG.topAnchor, constant: 50),
formStackView.bottomAnchor.constraint(equalTo: svCLG.bottomAnchor),
// constrain stack view Width to scroll view's Frame Layout Guide
// minus 40-pts, because we have 20-pts on each side
formStackView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor, constant: -40),
])
}
}
Related
These are my Outlets, how can I out all off these in an array?
#IBOutlet weak var progressBar1: UIProgressView!
#IBOutlet weak var progressBar2: UIProgressView!
#IBOutlet weak var progressBar3: UIProgressView!
#IBOutlet weak var progressBar4: UIProgressView!
Open the Assistant Editor, right-click and drag from one of your UIProgressView's or just drag from its "Referencing Outlet Collections" to the code file.
Insert outlet collection
Then you can drag from your swift file's #IBOutlet to the rest of your UIProgressView's. Add view to collection
On top declare a variable first like this
var outlets: [UIProgressView] = []
and now on ViewDidLoad method you can use this to put all outlets on that array
like this:
outlets = [progressBar1, progressBar2, progressBar3, progressBar4]
Hope you understand.
class ViewController: UIViewController {
#IBOutlet weak var p1: UIProgressView!
#IBOutlet weak var p2: UIProgressView!
#IBOutlet weak var p3: UIProgressView!
#IBOutlet weak var p4: UIProgressView!
var outlets: [UIProgressView] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
outlets = [
p1,p2,p3,p4
]
}
}
If you have other types of views you can use
var outlets: [UIView] = [...]
As mentioned here Swift - IBOutletCollection equivalent you can use IBOutletCollection to do that. You can drag all your views to one IBOutlet array.
#IBOutlet weak var progressBars: [UIProgressView]!
For example, you can access the first progressBar like
progressBars[0]
But you have to careful about the order of progressBars, when you define IBOutletCollections the collection will not be order guaranteed. You can define the for each view and sort by their tags in runtime as mentioned here also Is IBOutletCollection guaranteed to be of correct order?
To order all views by their tags like
progressBars = progressBars.sorted { $0.tag < $1.tag }
I have a view controller with a few labels and switches inside of it. Is there any way to make the whole view look "scrollable" like how UITableViewCells look. Like even if there isn't enough content to need it to be scrollable I want that interactive gesture that UITableViewCells have. The whole point of this is to make all the pages on my app feel similar. Is there any way to add that same "scrolling" or "dynamic" feeling to the normal view?
Edit: A link to show what I mean
https://imgur.com/a/wJtfIKK
Here is the code where I connect the scroll view and I am making it "scrollable"
class ThemesViewController: UIViewController {
#IBOutlet weak var spacer: UIView!
#IBOutlet weak var overrideThemeDesc: UILabel!
#IBOutlet weak var overrideSystemTheme: UILabel!
#IBOutlet weak var overrideThemeToggle: UISwitch!
#IBOutlet weak var backgroundView: UIView!
#IBOutlet weak var lightButton: RadioButton!
#IBOutlet weak var darkButton: RadioButton!
#IBOutlet weak var lightText: UILabel!
#IBOutlet weak var darkText: UILabel!
#IBOutlet weak var appearanceLabel: UILabel!
#IBOutlet var interactiveView: UIScrollView!
let themeOverrideDefaults = UserDefaults.standard
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
interactiveView.alwaysBounceVertical = true
// Rest of My Code
}
And here is a picture of the storyboard with the scroll view selected (to show it has custom class UIScrollView): https://imgur.com/a/YCKPKpj
You can embed your view into a UIScrollView and then set
scrollView.alwaysBounceVertical = true
so that you get that scrolling effect even if the content is not large enough to be scrolled.
https://developer.apple.com/documentation/uikit/uiscrollview/1619383-alwaysbouncevertical
I have a header label which I am adjusting the font size of, to fit to the size of the label. I would like to store the value of that font size so I can set the font size of some buttons to it.
I have tried to just store the pointSize of the label, but that just gives me the unadjusted value, not the value that is actually in effect.
The reason for this is, that I want the size of all the text in labels and buttons to look good on different sized iPad screens. But I am struggling with keeping the size the same, across multiple elements.
class ViewController: UIViewController {
#IBOutlet weak var essenceButton: UIButton!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var tribesButton: UIButton!
#IBOutlet weak var creaturesButton: UIButton!
#IBOutlet weak var monstersButton: UIButton!
#IBOutlet weak var musesButton: UIButton!
#IBOutlet weak var newsletterButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.titleLabel.adjustsFontSizeToFitWidth = true
let fontsize = self.titleLabel.font.pointSize
self.essenceButton.titleLabel?.font = essenceButton.titleLabel?.font.withSize(fontsize)
self.tribesButton.titleLabel?.font = tribesButton.titleLabel?.font.withSize(fontsize)
}
}
At viewDidLoad(), the view and its subviews (including the label) have not yet been laid out for the device's screen, so the label's font size has not changed.
You should be able to do this in viewWillLayoutSubviews():
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
view.layoutIfNeeded()
// Code to adjust font of the other UI items here
}
I have Same UILabel's in different viewcontrollers and I want to make the constraints of them global such that I should be able to edit them in one place and all viewcontrollers will adopt to it. To do that I have done something like this
#IBDesignable class TitleLabel: UILabel {
#IBOutlet weak var topConstraint: NSLayoutConstraint!
#IBOutlet weak var BottomConstraint: NSLayoutConstraint!
#IBOutlet weak var leftConstraint: NSLayoutConstraint!
#IBOutlet weak var rightConstraint: NSLayoutConstraint!
override func awakeFromNib() {
self.translatesAutoresizingMaskIntoConstraints = false
topConstraint.constant = 10
bottomConstraint.constant = 10
leftConstraint.constant = 20
rightConstraint.constant = 10
super.awakeFromNib()
}
}
So each of my label in different view controller is a TitleLabel and I connect its constraints in storyboard and change them in awakeFromNib()
Is there a better way then is approach for setting global constraints for same kind of label in different viewcontrollers?
I have a horizontal uistackview and i have 5 imageviews in it. I need to get id of the imageview that is tapped. I tried adding tap gesture identifier and get sender's id, but i am not getting it.
What i have tried till now is as follows
#IBOutlet weak var userRateViewStar1ImageOutlet : UIImageView!
#IBOutlet weak var userRateViewStar2ImageOutlet : UIImageView!
#IBOutlet weak var userRateViewStar3ImageOutlet : UIImageView!
#IBOutlet weak var userRateViewStar4ImageOutlet : UIImageView!
#IBOutlet weak var userRateViewStar5ImageOutlet : UIImageView!
#IBOutlet weak var userRateViewTextAreaOutlet : UITextView!
#IBOutlet var starOutletCollectionOutlet : [UIImageView]!
#IBAction func starRatingAction(_ sender: UITapGestureRecognizer)
{
var tag = sender.view!.tag
print(tag)
}
Basically i am trying to implement rate feature.
So can someone suggest me a way to implement this?
Thanks in advance
An easier way might be to create an IBOutletCollection e.g:
//1. Create An Array Of Your ImageViews
#IBOutlet var ratingStarImageViews: [UIImageView]!
Then assign a tag and the gesture to them e.g:
//2. Assign Tags To The Them
var tag = 0
for view in ratingStarImageViews{
let ratingGesture = UITapGestureRecognizer(target: self, action: #selector(starRatingAction(_:)))
view.addGestureRecognizer(ratingGesture)
view.tag = tag
tag += 1
}
Hope it helps.