swift second textview not visible - ios

I have an iOS project I'm working on using Xcode 9.2 and Swift4. I have a UITextView but second the UITextView not visible.
let logo: UIImageView = {
let imageView = UIImageView(image: #imageLiteral(resourceName: "logoyeni"));
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let bannerText: UITextView = {
let textView = UITextView()
textView.text = "Müziğin Sosyal Medyası";
textView.textColor = UIColor.salmon;
textView.textAlignment = .center
textView.isEditable = false
textView.translatesAutoresizingMaskIntoConstraints = false
textView.isScrollEnabled = false
return textView
}()
let slogan: UITextView = {
let textView1 = UITextView()
textView1.text = "Lorem Ipsum Dolor Sit Amet Consectetur";
//textView.font = UIFont.textStyle3;
//textView.textColor = UIColor.cloudyBlue;
textView1.textAlignment = .center;
textView1.isEditable = false
textView1.translatesAutoresizingMaskIntoConstraints = false;
return textView1
}()
ViewDidLoad =
super.viewDidLoad()
view.addSubview(logo);
view.addSubview(bannerText);
view.addSubview(slogan);
setup();
and constrains =
private func setup(){
logo.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
logo.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
logo.widthAnchor.constraint(equalToConstant: 127).isActive = true
logo.heightAnchor.constraint(equalToConstant: 127).isActive = true
bannerText.topAnchor.constraint(equalTo: logo.bottomAnchor, constant: 29).isActive = true
bannerText.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
bannerText.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
bannerText.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
slogan.topAnchor.constraint(equalTo: bannerText.bottomAnchor, constant: 4).isActive = true
slogan.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
slogan.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
slogan.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
}
How to fix this problem?

Your constraints are wrong.
bannerText.bottomAnchor = view.bottomAnchor
slogan.topAnchor = bannerText.bottomAnchor(view.bottomAnchor)
slogan.bottomAnchor = view.bottomAnchor
This will set the height of the second text view to zero.
You should have a height constraint for at least one of the text views rather than pinning both of them to the bottom of the superView.

You have pinned the bannerText to the bottom of the logo (offset by 29) and the left, right and bottom of the view.
You have then pinned the slogan to the bottom of the bannerText (offset by 4) and the left, right and bottom of the view.
That's not going to work because the bottom of the bannerText and the bottom of the view are the same and as the top of the slogan is the bottom of the view the top of slogan ends up being the bottom of the view and therefore it is outside the view (the constraints probably break as well).
You need to fix the constraints based on what you want to see.

Related

Why I cannot modify a UIScrollview leading edge programmatically?

I'm fairly new to iOS app development. I'm trying to make an iOS app which will have an horizontal scroll view with labels added as subviews which exhibit a snapping behaviour. I'm using UIKit and auto layouts (Swift 5, Xcode 12.01) for a programmatically build UI. I have three labels to be added to the scroll view, one is centred, one is offset 500 pt from the scrollview centre (right) and one is at -500 from the centre (left)
When I try to set the scrollview trailing anchor referring to the label on the right I have no problems. However, when I try to set the leading edge referring to the label on the left (leading edge), I encounter the error: [LayoutConstraints] Unable to simultaneously satisfy constraints.
Am I missing something?
I attach my code below:
// Create scroll view on top of bottom view
func createScrollView() -> UIScrollView {
let myScrollView = UIScrollView()
myScrollView.isScrollEnabled = true
myScrollView.backgroundColor = .red
myScrollView.showsHorizontalScrollIndicator = true
view.addSubview(myScrollView)
// Constraints
myScrollView.translatesAutoresizingMaskIntoConstraints = false
myScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
myScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
myScrollView.bottomAnchor.constraint(equalTo: bottomView.firstBaselineAnchor).isActive = true
myScrollView.heightAnchor.constraint(equalToConstant: 50).isActive = true
// Add some elements to the view
let label1 = UILabel()
let label2 = UILabel()
let label3 = UILabel()
label1.text = "EV 0."
label1.font = .systemFont(ofSize: 20)
label1.translatesAutoresizingMaskIntoConstraints = false
label2.text = "ISO"
label2.font = .systemFont(ofSize: 20)
label2.translatesAutoresizingMaskIntoConstraints = false
label3.text = "SNAP"
label3.font = .systemFont(ofSize: 20)
label3.translatesAutoresizingMaskIntoConstraints = false
// Add labels to scroll view
myScrollView.addSubview(label1)
myScrollView.addSubview(label2)
myScrollView.addSubview(label3)
// Add constraint
label1.centerYAnchor.constraint(equalTo: myScrollView.centerYAnchor).isActive = true
label2.centerYAnchor.constraint(equalTo: myScrollView.centerYAnchor).isActive = true
label3.centerYAnchor.constraint(equalTo: myScrollView.centerYAnchor).isActive = true
label1.centerXAnchor.constraint(equalTo: myScrollView.centerXAnchor, constant: -300).isActive = true
label2.centerXAnchor.constraint(equalTo: myScrollView.centerXAnchor, constant: 300).isActive = true
label3.centerXAnchor.constraint(equalTo: myScrollView.centerXAnchor, constant: 0).isActive = true
// Add last constraint in the scroll view
myScrollView.leadingAnchor.constraint(equalTo: label1.leadingAnchor, constant: -500).isActive = true
myScrollView.trailingAnchor.constraint(equalTo: label2.trailingAnchor, constant: 500).isActive = true
return myScrollView
Thanks a lot for your help!!!

Can't set UIView's background color Swift 5

I have a view that I initialise like this:
var view: UIView! = {
var perm = UIView()
perm.backgroundColor = UIColor.black
// enable auto layout
perm.translatesAutoresizingMaskIntoConstraints = false
return perm
}()
After that I add a label as a subview to view. The label is initialised like this:
var title: UILabel! = {
let perm = UILabel()
perm.textColor = UIColor.white
perm.numberOfLines = 0
perm.font = UIFont.boldSystemFont(ofSize: 20)
// enable auto layout
perm.translatesAutoresizingMaskIntoConstraints = false
return perm
}()
After that I add programmatically some constraints. When I run the app the title is displayed in the right position, but the view's background color has not been set.
EDIT
This is how I've set the constraints:
view.addSubview(title)
view.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
view.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: image.bottomAnchor).isActive = true
title.leadingAnchor.constraint(equalTo: title.superview!.leadingAnchor, constant: 20).isActive = true
title.trailingAnchor.constraint(equalTo: title.superview!.trailingAnchor, constant: -20).isActive = true
title.bottomAnchor.constraint(equalTo: title.superview!.bottomAnchor, constant: -20).isActive = true
view needs a height
view.heightAnchor.constraint(equalToConstant:200).isActive = true
OR For label height plus top and bottom padding 40
title.topAnchor.constraint(equalTo:view.topAnchor, constant:20).isActive = true

How do I add a UIView to a UIScrollView In Swift programmatically?

I am trying to add a view to a UIScrollView just using code, but the view doesn't appear in the UIScrollView and I'm not sure why. When I added a button or label, they show up.
import UIKit
class profileViewController: UIViewController, UIScrollViewDelegate {
var label : UILabel = {
let label = UILabel()
label.text = "Profile"
label.textColor = UIColor.init(white: 0.80, alpha: 1)
label.font = UIFont.systemFont(ofSize: 40)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
var scrollview : UIScrollView = {
let scrollview = UIScrollView()
scrollview.translatesAutoresizingMaskIntoConstraints = false
scrollview.backgroundColor = .clear
return scrollview
}()
var greyview : UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.init(white: 0.70, alpha: 1)
view.backgroundColor = UIColor.gray
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(label)
label.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor).isActive = true
label.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor).isActive = true
scrollview.delegate = self
view.addSubview(scrollview)
scrollview.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
scrollview.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
scrollview.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollview.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollview.contentSize = CGSize.init(width: view.frame.size.width, height: view.frame.size.height + 500)
scrollview.addSubview(greyview)
greyview.topAnchor.constraint(equalTo: scrollview.topAnchor).isActive = true
greyview.trailingAnchor.constraint(equalTo: scrollview.trailingAnchor).isActive = true
greyview.leadingAnchor.constraint(equalTo: scrollview.leadingAnchor).isActive = true
greyview.heightAnchor.constraint(equalToConstant: 100).isActive = true
}
}
this is one way:
self.scrollView = UIScrollView.init()
if let scrollView = self.scrollView {
scrollView.showsVerticalScrollIndicator = true
self.view.add(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
self.addConstraint(UtilConstraint.addTopConstraint(from: scrollView, to: self, value: 0))
self.addConstraint(UtilConstraint.addBottomConstraint(from: scrollView, to: self, value: 0))
self.addConstraint(UtilConstraint.addLeftLeftConstraint(from: scrollView, to: self, value: 0))
self.addConstraint(UtilConstraint.addRightRightConstraint(from: scrollView, to: self, value: 0))
NSLayoutConstraint.activate(self.constraints)
greyview.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(greyview)
greyview.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
greyview.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
greyview.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
greyview.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
}
Remember, your greyview should have hight defined either statically or via. components inside.
though , what you were missing was defining a width. I have done it using widthAnchor. (assuming you need a vertical scroll)
This is probably because your greyview doesnt have its bottomAnchor. It needs the top and bottom anchors in order to work properly inside the scrollView:
scrollview.addSubview(greyview)
greyview.topAnchor.constraint(equalTo: scrollview.topAnchor).isActive = true
greyview.centerXAnchor.constraint(equalTo: scrollview.centerXAnchor).isActive = true
greyview.heightAnchor.constraint(equalToConstant: 100).isActive = true
greyview.widthAnchor.constraint(equalToConstant: 100).isActive = true
Add a widthAnchor, here I centered it in the scroll view but it is up to you to place it how you want it. Also if you add more items just make sure the bottom-most item has a bottomAnchor attached to the scrollView bottomAnchor or it will not scroll.
Update:
I don't know how you want your greyview to look, but if you make the height taller than the contentSize of the scrollView it will scroll, and make sure you have the bottomAnchor:
scrollview.contentSize = CGSize.init(width: view.frame.size.width, height: view.frame.size.height)
scrollview.addSubview(greyview)
greyview.topAnchor.constraint(equalTo: scrollview.topAnchor).isActive = true
greyview.bottomAnchor.constraint(equalTo: scrollview.bottomAnchor).isActive = true
greyview.heightAnchor.constraint(equalTo: scrollview.heightAnchor, constant: 500).isActive = true
greyview.widthAnchor.constraint(equalTo: scrollview.widthAnchor).isActive = true
This makes the greyview width equal to scrollview width, and height equal to scrollview height + 500 so that it scrolls.

Setting constant width on subview of UIStackView when axis is vertical

I have a UIScrollView that contains a UIStackView, and I add views to it and if the UIStackView needs more space than the screen has then it will scroll thanks to the UIScrollView.
I am able to set constant heights on the views, but I also need to set a specific width on them, so that they have a specific width and are also centered in the stack view.
Something like this, except the widthAnchor does not work.
import UIKit
class ViewController: UIViewController {
let scrollView: UIScrollView = {
let sv = UIScrollView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.backgroundColor = .gray
return sv
}()
let stackView: UIStackView = {
let sv = UIStackView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.axis = .vertical
return sv
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(scrollView)
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
scrollView.addSubview(stackView)
stackView.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
stackView.rightAnchor.constraint(equalTo: scrollView.rightAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
let view1 = UIView()
view1.backgroundColor = .red
let view2 = UIView()
view2.backgroundColor = .blue
let view3 = UIView()
view3.backgroundColor = .green
let view4 = UIView()
view4.backgroundColor = .purple
stackView.addArrangedSubview(view1)
stackView.addArrangedSubview(view2)
stackView.addArrangedSubview(view3)
stackView.addArrangedSubview(view4)
view1.heightAnchor.constraint(equalToConstant: 200).isActive = true
view2.heightAnchor.constraint(equalToConstant: 300).isActive = true
view3.heightAnchor.constraint(equalToConstant: 420).isActive = true
view4.heightAnchor.constraint(equalToConstant: 100).isActive = true
// This does not work.
// view1.widthAnchor.constraint(equalToConstant: 40).isActive = true
}
}
The alignment property on a UIStackView determines how its layout works perpendicular to its axis. By default, a UIStackView has an alignment of fill. In constraint terms, fill is like adding a constraint to (in this case) the left and right edges of the stack view for each arranged subview. These implicit constraints are likely causing your problem. Solution: set stackView.alignment = either leading, center, or trailing depending on your desired effect.

Swift iOS -How to set UIView's Height Anchor <= To A Label's Intrinsic Text Size? 'NSLayoutConstraint' is not convertible to 'Bool'

I have a programmatic view with a label inside of it that I'm pinning to the bottom of the navBar. There will be dynamic text inside of the label and I want the view the label is in to be the at least 64 pts or bigger if the height of text makes it smaller.
The intrinsic size of the text from this label sets the view at a noticeable height.
setViewAndLabel(dynamicText: "Unknown Error\nPlease try your request again\Error: 123")
However the intrinsic size of this text makes the height to small:
setViewAndLabel(dynamicText: "Message Deleted!")
The Message Deleted! should be more along the lines of:
I used some return keys to set it like that but I don't think that's the correct way to go because different messages will get generated:
setViewAndLabel(dynamicText: "\nMessage Deleted!\n")
I also tried:
if myView.heightAnchor.constraint(lessThanOrEqualToConstant: 64){
myView.heightAnchor.constraint(equalToConstant: 64).isActive = true
}
But I get the error:
'NSLayoutConstraint' is not convertible to 'Bool'
What's the best way to set the height for the view the label is in to a minimum height?
var myLabel: UILabel(){
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = UIColor.white
label.font = UIFont(name: "Helvetica-Regular", size: 19)
label.numberOfLines = 0
label.sizeToFit()
label.textAlignment = .center
return label
}
let myView:UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated){
setViewAndLabel(dynamicText: //some text will get set here)
}
func setViewAndLabel(dynamicText: String){
view.addSubView(myView)
myView.backgroundColor = UIColor.red
myView.topAnchor.constraint(equalTo: view.topAnchor, constant: 64).isActive = true
View.widthAnchor.constraint(equalTo: view.widthAnchor, constant: 0).isActive = true
myView.addSubView(myLabel)
myLabel.text = dynamicText
myLabel.topAnchor.constraint(equalTo: myView.topAnchor, constant: 0).isActive = true
myLabel.widthAnchor.constraint(equalTo: myView.widthAnchor, constant: 0).isActive = true
myView.bottomAnchor.constraint(equalTo: myLabel.bottomAnchor, constant: 0).isActive = true
//this if statement doesn't work
if myView.heightAnchor.constraint(lessThanOrEqualToConstant: 64){
viewForErrorLabel.heightAnchor.constraint(equalToConstant: 64).isActive = true
}
}
This is how you have to set up your constraints:
view.addSubview(myView)
myView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true
myView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
myView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
myView.heightAnchor.constraint(greaterThanOrEqualToConstant: 64).isActive = true
myView.addSubview(myLabel)
myLabel.topAnchor.constraint(equalTo: myView.topAnchor).isActive = true
myLabel.leadingAnchor.constraint(equalTo: myView.leadingAnchor).isActive = true
myLabel.trailingAnchor.constraint(equalTo: myView.trailingAnchor).isActive = true
myLabel.bottomAnchor.constraint(equalTo: myView.bottomAnchor).isActive = true
You do not need to check the label's height at all. You can simply always create that height greater than or equal constraint for myView and its height will never be smaller than 64pt (or whatever value you set it to) - even if the label contains a very short text.

Resources