iOS: UILabel multi-line text get truncated in horizontal UIStackView - ios

Issue:
UILabel multi-line text get truncated in horizontal UIStackView.
I have a horizontal UIStackView, in this stack view, the left side is an UIImage, right side is a UILabel with some text.
The UILabel is a multiline UILabel, it should wrap itself if text is very long. However, in runtime it got truncated.
Any ideas on how to fix it?
My code below:
self.imageView = self.createIconImageView(...)
self.textLabel.text = text
self.textLabel.numberOfLines = 0 // which specify it is multi-line
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.alignment = .fill
stackView.distribution = .fillProportionally
stackView.spacing = 8.0
stackView.addArrangedSubview(self.imageView)
stackView.addArrangedSubview(self.textLabel)
self.containerView.addSubview(stackView)
stackView.edgesToSuperview(insets: Style.containerInsets)

alignment
/* The layout of the arrangedSubviews transverse to the axis;
e.g., leading/trailing edges in a vertical stack
*/
#property(nonatomic) UIStackViewAlignment alignment;
For .fill
StackView will automatically generate these layout attributes for you.
imageView.bottom == label.bottom
imageView.top == label.top
the size of stackView depend on the 'voice' image's size or size layout attributes of imageView as it is fixed instead of adjustable UILable which namely have the low priority.
For .center
StackView achieve a decent height by look for the max height between your label and imageView.
_UILayoutSpacer.bottom >= imageView.bottom
_UILayoutSpacer.bottom >= label.bottom
_UILayoutSpacer.top <= imageView.top
_UILayoutSpacer.top <= label.top

Related

How to center image in StackView conditionally

I have a StackView containing a UIImageView and a UILabel. Sometimes the UILabel contains a quotation and sometimes it does not. When it does I want the UIImageView to be 40% of the device width - I have that part working. When it does not I want the UIImageView still to be the same width, just centered horizontally. What's the easiest way to achieve this?
It seems that UIStackView is not what you really need there, but rather simple UIView, which is centered vertically in the parent view, and contains UIImageView and UILabel, and then set imageView.trailing equal to label.leading, plus label.sizeToFit().
But if you want to stick to your design, what you could do is programmatically set UIStackView axes. For instance, set stack view in IB like:
UIStackView IB setting
and then in code in viewDidLoad() method:
if label.text == "" {
stackView.axis = .vertical
} else {
stackView.axis = .horizontal
}
also with label.sizeToFit().
That should do the trick.

3 equal height views using autolayout programmatically

I am a beginner in autolayout. I have all my views created programmatically.
What I want is 3 equal height vertical splits using autolayout programmatically?
My expectation is in portrait or landscape the height of all 3 views will adjust and width will remain same (screenwidth)
Could you please provide me with an example?
Have you tried using a UIStackView?
lazy var stackView: UIStackView = {
let stackView: UIStackView = UIStackView(arrangedSubviews: [self.firstView, self.secondView, self.thirdView])
stackView.axis = UILayoutConstraintAxis.vertical
stackView.distribution = UIStackViewDistribution.fillEqually
stackView.alignment = UIStackViewAlignment.fill
stackView.spacing = 10.0
return stackView
}()
Then use autolayout to make the height of one of the view's height. The stackView will take care of the other two views' height
Use a vertical stack view by dragging "Vertical Stack View" UIStackView from the object library. Set up it's auto layout constraints and divide it in the number of pieces you need. You don't need to manage it from your code.

Xcode Autolayout How to centre uitextfield with fixed width that can adjust for smaller screens

I can't seem to form how the constraints will work, so in Descriptive terms:
the textfield is horizontally center to the container
the textfield is 100 points offset from the top layout guide
the textfield is 370points wide.
if the container shrinks in width smaller than 370 points it will adjust proportionally
if the screen goes wider the text field does not resize but stays at 370 points
I can more or less define constraints for most of them except for the ability to constrain its width automatically if the screen shrinks in width for smaller screen sizes.
Some pointers would be good
Thanks!
You can add a leading and trailing constraint to your textField with a lower priority. And simply add a width constraint that can be <= 370.
This should do it:
let textField = UITextField()
view.addSubview(textField)
textField.translatesAutoresizingMaskIntoConstraints = false
// center horizontally
textField.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
// 100 from top layout guide
textField.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 100).isActive = true
// make sure textfield width never exceeds the superview width
textField.leftAnchor.constraint(greaterThanOrEqualTo: view.leftAnchor).isActive = true
textField.rightAnchor.constraint(lessThanOrEqualTo: view.rightAnchor).isActive = true
// give the textfield its default width, notice the lowered priority which allows this constraint to be broken when needed to satisfy the above constraints
let widthConstraint = textField.widthAnchor.constraint(equalToConstant: 370)
widthConstraint.priority = UILayoutPriorityDefaultHigh
widthConstraint.isActive = true

Arrange UILabels in UIstackView Dynamically

I am adding labels as subview to UIstackview using arrangedSubView property.
what happens is that if I keep Stackview axis horizontal,
I get one horizontal strip of UILabels
label1 label2 label3 label4.....
if I keep it vertical, I get a vertical strip of UILabels
like below
label1
label2
label3
and so on
But what I am trying to achieve is this
label1, label2(if it fits) otherwise take it below
label3, label4
label5 and so on
presently my code is this
uiLabel1.numberOfLines = 1
uiLabel1.backgroundColor = THEMECOLOR
uiLabel1.font = UIFont.preferredFontForTextStyle(UIFontTextStyleCaption1)
uiLabel1.textColor = topicColor
uiLabel1.layer.cornerRadius = (CGFloat)(5.0)
uiLabel1.layer.masksToBounds = true
uiLabel1.sizeToFit()
uiLabel1.userInteractionEnabled = true
self.dynamicStackView.addArrangedSubview(uiLabel1)
I believe Flow Layout of the UICollectionView is what you need. Have a look at the link here

Multiline UILabel inside UIScrollView

I can't make multiple lines for a label inside the scroll view. Though it perfectly works outside of a scrollview. See picture below for details. The scroll view has a horizontal scroll.
UPD: ScrollView and label constraints:
So apparently I need explicitly set ScrollView contentSize. Also to get this size I need to know it from a label which is a bit tricky here. The full code goes below:
// create a label as usual
let label = UILabel()
label.numberOfLines = 0
label.text = "really long label text..."
// place it with a nice offset and set its width explicitly using parent view width
// after which `sizeToFit` does a trick and adjusts it's height
label.frame.offset(dx: 16.0, dy: 16.0)
label.frame.size.width = self.view.frame.width - 32
label.sizeToFit()
// now add it to the scroll view and set content size to label size plus margin at the bottom
self.scrollView.addSubview(label)
self.scrollView.contentSize = label.frame.size
self.scrollView.contentSize.height += 32

Resources