I am trying to build a vertical stack view with a UI label and multiple horizontal stack views, However, I only see the multiple horizontal stacks in the UI and not the UI label. Here is some code
final class FinalView: UIView {
let mainStackView = UIStackView()
init() {
super.init(frame: .zero)
let label: UILabel = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Sorry ?"
...
let verticalStackView = UIStackView(arrangedSubviews: multiplehorizontalViews)
verticalStackView.axis = .vertical
verticalStackView.translatesAutoresizingMaskIntoConstraints = false
verticalStackView.spacing = 5.0
mainStackView.addArrangedSubview(label)
mainStackView.addArrangedSubview(verticalStackView)
mainStackView.translatesAutoresizingMaskIntoConstraints = false
mainStackView.axis = .vertical
}
}
I am only seeing verticalStackView but not label. When I removed this mainStackView.addArrangedSubview(verticalStackView) from the code, I can see the label. But When it is there I can't see the label. Any ideas on the issue or any tips for debugging?
Your code is working completely fine. Just checked on iOS 13 with below code
let mainStackView = UIStackView()
mainStackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(mainStackView)
var vflString = "V:|-[mainStackView]-|"
var vflConstraints = NSLayoutConstraint.constraints(withVisualFormat: vflString, options: [], metrics: nil, views: ["mainStackView" : mainStackView])
view.addConstraints(vflConstraints)
vflString = "H:|-[mainStackView]-|"
vflConstraints = NSLayoutConstraint.constraints(withVisualFormat: vflString, options: [], metrics: nil, views: ["mainStackView" : mainStackView])
view.addConstraints(vflConstraints)
let label: UILabel = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Sorry ?"
let label1 = UILabel(frame: .zero)
label1.text = "Label 1"
let label2 = UILabel(frame: .zero)
label2.text = "Label 2"
let label3 = UILabel(frame: .zero)
label3.text = "Label 3"
let multiplehorizontalViews = [label1, label2, label3]
let verticalStackView = UIStackView(arrangedSubviews: multiplehorizontalViews)
verticalStackView.axis = .horizontal
verticalStackView.translatesAutoresizingMaskIntoConstraints = false
verticalStackView.spacing = 5.0
verticalStackView.distribution = .fillProportionally
mainStackView.addArrangedSubview(label)
mainStackView.addArrangedSubview(verticalStackView)
mainStackView.translatesAutoresizingMaskIntoConstraints = false
mainStackView.axis = .vertical
I'm pretty sure it's not your case but in mine
this applied:
UIBezierPath: roundedRect: byRoundingCorners: cornerRadii: acts weird
bezier path on layer was cutting all content from the stackview
you can check in the visual debugger what's going in: if the labels
text show up there then it's an issue with layer clipping
Related
So, I added some text (UITextView) to my stackView and centered to the top. I also added a UIImageView which would sit nicely under my UITextView. Well it doesn't. For some reason the image covers the text completely. If I delete the image the text comes back up nice on the top center. Played a lot with the stack distribution and alignment but no luck. Not sure what I'm missing :(. Any help is appreciated!
I'm adding both the UITextView and UIIMageView as arrangedSubview to the stack.
Here is my code:
//stack
let stack: UIStackView = {
let stack = UIStackView()
stack.translatesAutoresizingMaskIntoConstraints = false
stack.axis = .vertical
stack.spacing = 5
stack.distribution = .fillProportionally
stack.alignment = .fill
return stack
}()
//text
fileprivate let title: UITextView = {
let title = UITextView()
title.translatesAutoresizingMaskIntoConstraints = false
title.contentMode = .scaleAspectFit
title.layer.cornerRadius = 10
title.backgroundColor = .darkGray
title.font = UIFont(name: "Megrim-Regular", size: 17)
title.textColor = .white
title.textAlignment = .center
return title
}()
//image
let image: UIImageView = {
let image = UIImageView()
image.image = UIImage(named: "demoPic.jpg")
image.translatesAutoresizingMaskIntoConstraints = false
image.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
return image
}()
Hope this below may help,
I think your issue is relating to constraints applied to the stackview and the holder view. (See below)
Your UI Elements (TextView & Image) code seems to be fine (maybe the image will not be work with 50 width /50 height inside this particular stack view configuration. It will require a different approach IMO.
Nevertheless on my playground in order to see it, I just applied 2 constraints towards my container view in order to see your TextView well above your ImageView as you wanted.
Here is the playground I used to reproduce your issue, you can copy and paste it to see if it fits what you request.
import UIKit
import PlaygroundSupport
/// DEMO VIEW CLASS
final class DemoView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
}
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented")
}
}
// YOUR UI CODE
//stack
let stack: UIStackView = {
let stack = UIStackView()
stack.translatesAutoresizingMaskIntoConstraints = false
stack.axis = .vertical
stack.spacing = 5
stack.distribution = .fillProportionally
stack.alignment = .fill
return stack
}()
//text
fileprivate let title: UITextView = {
let title = UITextView()
title.translatesAutoresizingMaskIntoConstraints = false
title.contentMode = .scaleAspectFit
title.layer.cornerRadius = 10
title.backgroundColor = .darkGray
title.font = UIFont(name: "Megrim-Regular", size: 17)
title.text = "TextView"
title.textColor = .white
title.textAlignment = .center
return title
}()
//image
let image: UIImageView = {
let image = UIImageView()
image.backgroundColor = .red
image.translatesAutoresizingMaskIntoConstraints = false
image.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
return image
}()
// PLAYGROUND DEMO VIEW TO HOLD YOUR STACK VIEW
let demoView = DemoView(frame: CGRect(x: 0, y: 0, width: 350, height: 150))
stack.addArrangedSubview(title)
stack.addArrangedSubview(image)
demoView.addSubview(stack)
demoView.addConstraints(
NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[stackView]-0-|",
options: NSLayoutConstraint.FormatOptions(rawValue: 0),
metrics: nil,
views: ["stackView": stack])
)
demoView.addConstraints(
NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[stackView]-0-|",
options: NSLayoutConstraint.FormatOptions(rawValue: 0),
metrics: nil,
views: ["stackView": stack])
)
PlaygroundPage.current.liveView = demoView
Results: Your Text View is above the image center (ImageView just have a RED Background here).
Embedd StackView in ScrollView that is embedded in a main StackView
I am having trouble with a rather complicated detail view that I want to do programmatically. My view hierarchy looks something like this:
Since this might be better explained visualising, I have a screenshot here:
My problem is that I don't know how to set the height constraint on descriptionTextView – right now it's set to 400. What I want though is that it takes up all the space available as the middle item of the main stack view. Once one or more comments are added to the contentStackView, the text field should shrink.
I am not sure which constraints for which views I must set to achieve this...
Here's my take on it so far:
import UIKit
class DetailSampleViewController: UIViewController {
lazy var mainStackView: UIStackView = {
let m = UIStackView()
m.axis = .vertical
m.alignment = .fill
m.distribution = .fill
m.spacing = 10
m.translatesAutoresizingMaskIntoConstraints = false
m.addArrangedSubview(titleTextField)
m.addArrangedSubview(contentScrollView)
m.addArrangedSubview(footerStackView)
return m
}()
lazy var titleTextField: UITextField = {
let t = UITextField()
t.borderStyle = .roundedRect
t.placeholder = "Some Fancy Placeholder"
t.text = "Some Fancy Title"
t.translatesAutoresizingMaskIntoConstraints = false
return t
}()
lazy var contentScrollView: UIScrollView = {
let s = UIScrollView()
s.contentMode = .scaleToFill
s.keyboardDismissMode = .onDrag
s.translatesAutoresizingMaskIntoConstraints = false
s.addSubview(contentStackView)
return s
}()
lazy var contentStackView: UIStackView = {
let s = UIStackView()
s.translatesAutoresizingMaskIntoConstraints = false
s.axis = .vertical
s.alignment = .fill
s.distribution = .equalSpacing
s.spacing = 10
s.contentMode = .scaleToFill
s.addArrangedSubview(descriptionTextView)
s.addArrangedSubview(getCommentLabel(with: "Some fancy comment"))
s.addArrangedSubview(getCommentLabel(with: "Another fancy comment"))
s.addArrangedSubview(getCommentLabel(with: "And..."))
s.addArrangedSubview(getCommentLabel(with: "..even..."))
s.addArrangedSubview(getCommentLabel(with: "...more..."))
s.addArrangedSubview(getCommentLabel(with: "...comments..."))
s.addArrangedSubview(getCommentLabel(with: "Some fancy comment"))
s.addArrangedSubview(getCommentLabel(with: "Another fancy comment"))
s.addArrangedSubview(getCommentLabel(with: "And..."))
s.addArrangedSubview(getCommentLabel(with: "..even..."))
s.addArrangedSubview(getCommentLabel(with: "...more..."))
s.addArrangedSubview(getCommentLabel(with: "...comments..."))
return s
}()
lazy var descriptionTextView: UITextView = {
let tv = UITextView()
tv.font = UIFont.systemFont(ofSize: 17.0)
tv.clipsToBounds = true
tv.layer.cornerRadius = 5.0
tv.layer.borderWidth = 0.25
tv.translatesAutoresizingMaskIntoConstraints = false
tv.text = """
Some fancy textfield text,
spanning over multiple
lines
...
"""
return tv
}()
lazy var footerStackView: UIStackView = {
let f = UIStackView()
f.axis = .horizontal
f.alignment = .fill
f.distribution = .fillEqually
let commentLabel = UILabel()
commentLabel.text = "Comments"
let addCommentButton = UIButton(type: UIButton.ButtonType.system)
addCommentButton.setTitle("Add Comment", for: .normal)
f.addArrangedSubview(commentLabel)
f.addArrangedSubview(addCommentButton)
return f
}()
override func loadView() {
view = UIView()
view.backgroundColor = . systemBackground
navigationController?.isToolbarHidden = true
view.addSubview(mainStackView)
NSLayoutConstraint.activate([
mainStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 12),
mainStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -12),
mainStackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12),
mainStackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12),
titleTextField.heightAnchor.constraint(equalToConstant: titleTextField.intrinsicContentSize.height),
contentStackView.leadingAnchor.constraint(equalTo: contentScrollView.leadingAnchor),
contentStackView.trailingAnchor.constraint(equalTo: contentScrollView.trailingAnchor),
contentStackView.topAnchor.constraint(equalTo: contentScrollView.topAnchor),
contentStackView.bottomAnchor.constraint(equalTo: contentScrollView.bottomAnchor),
descriptionTextView.heightAnchor.constraint(equalToConstant: 400),
descriptionTextView.leadingAnchor.constraint(equalTo: mainStackView.leadingAnchor),
descriptionTextView.trailingAnchor.constraint(equalTo: mainStackView.trailingAnchor),
])
}
override func viewDidLoad() {
super.viewDidLoad()
title = "Detail View"
}
func getCommentLabel(with text: String) -> UILabel {
let l = UILabel()
l.layer.borderWidth = 0.25
l.translatesAutoresizingMaskIntoConstraints = false
l.text = text
return l
}
}
You're close, but a couple notes:
When using stack views - particularly inside scroll views - you sometimes need to explicitly define which elements can be stretched or not, and which elements can be compressed or not.
To get the scroll view filled before it has enough content, you need to set constraints so the combined content height is equal to the scroll view frame's height, but give that constraint a low priority so auto-layout can "break" it when you have enough vertical content.
A personal preference: I'm generally not a fan of adding subviews inside lazy var declarations. It can become confusing when trying to setup constraints.
I've re-worked your posted code to at least get close to what you're going for. It starts with NO comment labels... tapping the "Add Comment" button will add "numbered comment labels" and every third comment will wrap onto multiple lines.
Not really all that much in the way of changes... and I think I added enough comments to make things clear.
class DetailSampleViewController: UIViewController {
lazy var mainStackView: UIStackView = {
let m = UIStackView()
m.axis = .vertical
m.alignment = .fill
m.distribution = .fill
m.spacing = 10
m.translatesAutoresizingMaskIntoConstraints = false
// don't add subviews here
return m
}()
lazy var titleTextField: UITextField = {
let t = UITextField()
t.borderStyle = .roundedRect
t.placeholder = "Some Fancy Placeholder"
t.text = "Some Fancy Title"
t.translatesAutoresizingMaskIntoConstraints = false
return t
}()
lazy var contentScrollView: UIScrollView = {
let s = UIScrollView()
s.contentMode = .scaleToFill
s.keyboardDismissMode = .onDrag
s.translatesAutoresizingMaskIntoConstraints = false
// don't add subviews here
return s
}()
lazy var contentStackView: UIStackView = {
let s = UIStackView()
s.translatesAutoresizingMaskIntoConstraints = false
s.axis = .vertical
s.alignment = .fill
// distribution needs to be .fill (not .equalSpacing)
s.distribution = .fill
s.spacing = 10
s.contentMode = .scaleToFill
// don't add subviews here
return s
}()
lazy var descriptionTextView: UITextView = {
let tv = UITextView()
tv.font = UIFont.systemFont(ofSize: 17.0)
tv.clipsToBounds = true
tv.layer.cornerRadius = 5.0
tv.layer.borderWidth = 0.25
tv.translatesAutoresizingMaskIntoConstraints = false
tv.text = """
Some fancy textfield text,
spanning over multiple lines.
This textView now has a minimum height of 160-pts.
"""
return tv
}()
lazy var footerStackView: UIStackView = {
let f = UIStackView()
f.axis = .horizontal
f.alignment = .fill
f.distribution = .fillEqually
let commentLabel = UILabel()
commentLabel.text = "Comments"
let addCommentButton = UIButton(type: UIButton.ButtonType.system)
addCommentButton.setTitle("Add Comment", for: .normal)
// add a target so we can add comment labels
addCommentButton.addTarget(self, action: #selector(addCommentLabel(_:)), for: .touchUpInside)
// don't allow button height to be compressed
addCommentButton.setContentCompressionResistancePriority(.required, for: .vertical)
f.addArrangedSubview(commentLabel)
f.addArrangedSubview(addCommentButton)
return f
}()
// just for demo - numbers the added comment labels
var commentIndex: Int = 0
// do all this in viewDidLoad(), not in loadView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = . systemBackground
navigationController?.isToolbarHidden = true
title = "Detail View"
// add the mainStackView
view.addSubview(mainStackView)
// add elements to mainStackView
mainStackView.addArrangedSubview(titleTextField)
mainStackView.addArrangedSubview(contentScrollView)
mainStackView.addArrangedSubview(footerStackView)
// add contentStackView to contentScrollView
contentScrollView.addSubview(contentStackView)
// add descriptionTextView to contentStackView
contentStackView.addArrangedSubview(descriptionTextView)
// tell contentStackView to be the height of contentScrollView frame
let contentStackHeight = contentStackView.heightAnchor.constraint(equalTo: contentScrollView.frameLayoutGuide.heightAnchor)
// but give it a lower priority do it can grow as comment labels are added
contentStackHeight.priority = .defaultLow
NSLayoutConstraint.activate([
// constrain mainStackView top / bottom / leading / trailing to safe area
mainStackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 12),
mainStackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -12),
mainStackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12),
mainStackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12),
// title text field
titleTextField.heightAnchor.constraint(equalToConstant: titleTextField.intrinsicContentSize.height),
// minimum height for descriptionTextView
descriptionTextView.heightAnchor.constraint(greaterThanOrEqualToConstant: 160.0),
// constrain contentStackView top / leading / trailing / bottom to contentScrollView
contentStackView.topAnchor.constraint(equalTo: contentScrollView.topAnchor),
contentStackView.leadingAnchor.constraint(equalTo: contentScrollView.leadingAnchor),
contentStackView.trailingAnchor.constraint(equalTo: contentScrollView.trailingAnchor),
contentStackView.bottomAnchor.constraint(equalTo: contentScrollView.bottomAnchor),
// constrain contentStackView width to contentScrollView frame
contentStackView.widthAnchor.constraint(equalTo: contentScrollView.frameLayoutGuide.widthAnchor),
// activate contentStackHeight constraint
contentStackHeight,
])
// during dev, give some background colors so we can see the frames
contentScrollView.backgroundColor = .cyan
descriptionTextView.backgroundColor = .yellow
}
#objc func addCommentLabel(_ sender: Any?) -> Void {
// commentIndex is just used to number the added comments
commentIndex += 1
// let's make every third label end up with multiple lines, just to
// confirm variable-height labels won't mess things up
var s = "This is label \(commentIndex)"
if commentIndex % 3 == 0 {
s += ", and it has enough text that it should need to wrap onto multiple lines, even in landscape orientation."
}
let v = getCommentLabel(with: s)
// don't let comment labels stretch vertically
v.setContentHuggingPriority(.required, for: .vertical)
// don't let comment labels get compressed vertically
v.setContentCompressionResistancePriority(.required, for: .vertical)
contentStackView.addArrangedSubview(v)
// auto-scroll to bottom to show newly added comment label
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
let r = CGRect(x: 0.0, y: self.contentScrollView.contentSize.height - 1.0, width: 1.0, height: 1.0)
self.contentScrollView.scrollRectToVisible(r, animated: true)
}
}
func getCommentLabel(with text: String) -> UILabel {
let l = UILabel()
l.layer.borderWidth = 0.25
l.translatesAutoresizingMaskIntoConstraints = false
l.text = text
// allow wrapping / multi-line comments
l.numberOfLines = 0
return l
}
}
I want to achieve this requirement
if vertical stack has two label than Text should be centre aligned to image
and if not than top aligned to Image
How can I achieve this without writing any code
You'll need to control the alignment of the outer (i.e final stack view which contains both the image and the labels' stack view) stack view.
As you will need to control which labels need to be added to the labels' stack view, I assume you will be doing this programmatically. So basically you'll need:
finalStackView.alignment = labelsStackView.arrangedSubviews.count > 2 ? .top : .center
Here is a complete example which produces the below outputs:
class ViewController: UIViewController {
let finalStackView = UIStackView()
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.heightAnchor.constraint(equalToConstant: 200).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 200).isActive = true
imageView.image = #imageLiteral(resourceName: "taylor-swift")
let label1 = UILabel()
let label2 = UILabel()
let label3 = UILabel()
let label4 = UILabel()
label1.translatesAutoresizingMaskIntoConstraints = false
label2.translatesAutoresizingMaskIntoConstraints = false
label3.translatesAutoresizingMaskIntoConstraints = false
label4.translatesAutoresizingMaskIntoConstraints = false
label1.text = "Hello"
label2.text = "72 mins"
label3.text = "Hello 3"
label4.text = "Hello 4"
let labelsStackView = UIStackView(arrangedSubviews: [label1, label2, label3, label4])
labelsStackView.translatesAutoresizingMaskIntoConstraints = false
labelsStackView.axis = .vertical
labelsStackView.distribution = .fill
labelsStackView.alignment = .leading
finalStackView.addArrangedSubview(imageView)
finalStackView.addArrangedSubview(labelsStackView)
finalStackView.axis = .horizontal
finalStackView.distribution = .fill
finalStackView.alignment = labelsStackView.arrangedSubviews.count > 2 ? .top : .center
view.addSubview(finalStackView)
finalStackView.translatesAutoresizingMaskIntoConstraints = false
finalStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
finalStackView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
finalStackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
}
With the exact code above the output is:
With 2 labels added to the labelsStackView, the output is:
Keep the labels vertical stackview in a Horizontal stackView.
if you have more than 2 labels, change Horizontal stackView alignment to top else keep it to center.
Your layout structure be like
> main stack view (Horizontal)
> Image
> stack view (Horizontal)
>labels stack view (Vertical)
> Labels
I have a UIStackView which needs a background color in one of the stacks, so I placed a UIView inside, but the UIView is never displayed. The UIView currently has one subview, a UILabel, but should eventually have another UIStackView instead. If I display the UILabel as a direct child of the UIStackView, rather than the UIView, then the UILabel displays properly. So, what constraints are missing or wrong on my UIView?
let stack = UIStackView()
stack.axis = .Vertical
stack.alignment = .Leading
stack.distribution = .EqualCentering
stack.spacing = 0
let width = UIScreen.mainScreen().bounds.size.width
let frame = CGRect(x: 0, y: 0, width: width, height: 50)
let viewHolder = UIView(frame: frame)
viewHolder.backgroundColor = blueColor
//Needs a blue background
let name = UILabel()
name.text = nameText
name.textColor = yellowColor
name.backgroundColor = blueColor
name.font = UIFont.boldSystemFontOfSize(32.0)
let address = UILabel()
address.text = addressText
let dateTime = UILabel()
dateTime.text = calString
viewHolder.addSubview(name)
stack.addArrangedSubview(viewHolder)
stack.addArrangedSubview(address)
stack.addArrangedSubview(dateTime)
self.stackView.addArrangedSubview(stack)
And when run it produces this:
If I remove the UIView from the equation, ie:
let stack = UIStackView()
stack.axis = .Vertical
stack.alignment = .Leading
stack.distribution = .EqualCentering
stack.spacing = 0
let width = UIScreen.mainScreen().bounds.size.width
let frame = CGRect(x: 0, y: 0, width: width, height: 50)
let viewHolder = UIView(frame: frame)
viewHolder.backgroundColor = blueColor
//Needs a blue background
let name = UILabel()
name.text = nameText
name.textColor = yellowColor
name.backgroundColor = blueColor
name.font = UIFont.boldSystemFontOfSize(32.0)
let address = UILabel()
address.text = addressText
let dateTime = UILabel()
dateTime.text = calString
//viewHolder.addSubview(name)
stack.addArrangedSubview(name) //Add the label directly to the UIStackView
stack.addArrangedSubview(address)
stack.addArrangedSubview(dateTime)
self.stackView.addArrangedSubview(stack)
I get:
I just need the blue part to stretch across the screen
So, answer is, don't use UIStackView. Use the built in UITableView for this kind of layout.
I want to add several multiline Labels to an UIStackView.
But I always end up my Labels being truncated. As seen in this Screenshot
But I like to have it more as shown here (my faked Screenshot)
Here is my Code. First I create the parent/master StackView, put it into an ScrollView (which is tucked to the screen)
stackView = UIStackView()
stackView.axis = .Vertical
stackView.distribution = .Fill
stackView.spacing = 2
stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(stackView)
NSLayoutConstraint.activateConstraints(stackConstraints)
let s1 = createHeaderStackView()
stackView.insertArrangedSubview(s1, atIndex: 0)
let lbl2 = makeLabel()
lbl2.text = "Second One"
stackView.insertArrangedSubview(lbl2, atIndex: 1)
scrollView.setNeedsLayout()
while makeLabel and makeButton are just helper functions
func makeButton() -> UIButton {
let btn = UIButton(type: .Custom)
btn.backgroundColor = UIColor.lightGrayColor()
return btn
}
func makeLabel() -> UILabel {
let lbl = UILabel()
lbl.font = UIFont.systemFontOfSize(18)
lbl.setContentCompressionResistancePriority(1000, forAxis: .Vertical)
lbl.setContentHuggingPriority(10, forAxis: .Vertical)
lbl.preferredMaxLayoutWidth = scrollView.frame.width
lbl.numberOfLines = 0
lbl.textColor = UIColor.blackColor()
lbl.backgroundColor = UIColor.redColor()
return lbl
}
The createHeaderStackViewmethod is to configure my StackView to put inside a StackView with all my header stuff.
func createHeaderStackView() -> UIStackView {
let lblHeader = makeLabel()
lblHeader.text = "UIStackView"
lblHeader.textAlignment = .Center
let lblInfo = makeLabel()
lblInfo.text = "This is a long text, over several Lines. Because why not and am able to to so, unfortunaltey Stackview thinks I'm not allowed."
lblInfo.textAlignment = .Natural
lblInfo.layoutIfNeeded()
let lblInfo2 = makeLabel()
lblInfo2.text = "This is a seconds long text, over several Lines. Because why not and am able to to so, unfortunaltey Stackview thinks I'm not allowed."
lblInfo2.textAlignment = .Natural
lblInfo2.layoutIfNeeded()
let btnPortal = makeButton()
btnPortal.setTitle("My Button", forState: .Normal)
btnPortal.addTarget(self, action: "gotoPushWebPortalAction", forControlEvents: .TouchUpInside)
let headerStackView = UIStackView(arrangedSubviews: [lblHeader, btnPortal, lblInfo, lblInfo2])
headerStackView.axis = .Vertical
headerStackView.alignment = .Center
headerStackView.distribution = .Fill
headerStackView.spacing = 2
headerStackView.setContentCompressionResistancePriority(1000, forAxis: .Vertical)
headerStackView.setContentHuggingPriority(10, forAxis: .Vertical)
headerStackView.setNeedsUpdateConstraints()
headerStackView.setNeedsLayout()
//headerStackView.layoutMarginsRelativeArrangement = true
return headerStackView
}
so to make a long story short: What is needed to adjust my stackviews, so each stackview and therefore label is shown in full glorious size? I tried to compress and hug everything, but it didn't seem to work. And googling uistackview uilabel multiline truncated seems to be a dead end, too
I appreciate any help,
regards Flori
You have to specify the dimensions of the stack view. The label will not "overflow" into the next line if the dimensions of the stack view is ambiguous.
This code is not exactly the output you'd want, but you'll get the idea:
override func viewDidLoad() {
super.viewDidLoad()
let stackView = UIStackView()
stackView.axis = .Vertical
stackView.distribution = .Fill
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
let views = ["stackView" : stackView]
let h = NSLayoutConstraint.constraintsWithVisualFormat("H:|-50-[stackView]-50-|", options: [], metrics: nil, views: views)
let w = NSLayoutConstraint.constraintsWithVisualFormat("V:|-100-[stackView]-50-|", options: [], metrics: nil, views: views)
view.addConstraints(h)
view.addConstraints(w)
let lbl = UILabel()
lbl.preferredMaxLayoutWidth = stackView.frame.width
lbl.numberOfLines = 0
lbl.text = "asddf jk;v ijdor vlb otid jkd;io dfbi djior dijt ioure f i;or dfuu;nfg ior mf;drt asddf jk;v ijdor vlb otid jkd;io dfbi djior dijt ioure f infg ior mf;drt asddf jk;v ijdor vlb otid jkd;io dfbi djior dijt ioure f i;or dfuu;nfg ior mf;drt "
dispatch_async(dispatch_get_main_queue(), {
stackView.insertArrangedSubview(lbl, atIndex: 0)
})
}
As per I know If you are using this inside UITableViewCell then each rotation you have to reload tableView.
You can use stackView.distribution = .fillProportionally it will work fine.
You should try this on storyboard.
make the stackview height as equal to 60% or 70% of your view.
Make the multiplier as 0.6 or 0.7.