I have an UIImageView
inside UIView
which is inside an horizontal UIStackView
(with .fillEqually option). Horizontal UIStackView
has two views always. Horizontal UIStackView
gets its height from the Its' highest sub UIView
.
What I want to achieve: In the example screenshot, UIImageView has a bigger size when you consider with the multiline views because of its image size. However, I want that image view shrinks to the size that fits left (multiline label) view. This is shown in the second screenshot. Image should has a height of which I show via red oval line on the right side.
UIImageView with label Class:
@IBDesignable class LabelWithImage: UIView {
var topMargin: CGFloat = 0.0
var verticalSpacing: CGFloat = 10.0
var bottomMargin: CGFloat = 0.0
@IBInspectable var labelText: String = "" { didSet { updateView() } }
@IBInspectable var image: UIImage = UIImage(named: "harcamagrafik")! { didSet { updateView() } }
fileprivate var label: UILabel!
fileprivate var imageView: UIImageView!
override init(frame: CGRect) {
super.init(frame: frame)
setUpView()
}
required public init?(coder: NSCoder) {
super.init(coder:coder)
setUpView()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setUpView()
}
func setUpView() {
label = UILabel()
label.font = UIFont.init(name: "Metropolis-Medium", size: 12)
label.numberOfLines = 1
label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.textColor = UIColor.init(rgb: 0x9B9B9B)
imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
addSubview(label)
addSubview(imageView)
label .translatesAutoresizingMaskIntoConstraints = false
imageView.translatesAutoresizingMaskIntoConstraints = false
setContentHuggingPriority(.init(rawValue: 1000.0), for: .vertical)
setContentCompressionResistancePriority(.init(rawValue: 10.0), for: .vertical)
label.leftAnchor.constraint(equalTo: leftAnchor, constant: 0.0).isActive = true
// imageView.leftAnchor.constraint(equalTo: leftAnchor, constant: 0.0).isActive = true
label.rightAnchor.constraint(equalTo: rightAnchor, constant: 0.0).isActive = true
// imageView.rightAnchor.constraint(equalTo: rightAnchor, constant: 0.0).isActive = true
imageView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
label.topAnchor.constraint(equalTo: topAnchor, constant: topMargin).isActive = true
imageView.topAnchor.constraint(equalTo: label.bottomAnchor, constant: verticalSpacing).isActive = true
bottomAnchor.constraint(equalTo: imageView.bottomAnchor, constant: bottomMargin).isActive = true
// call common "refresh" func
updateView()
}
func updateView() {
label.text = labelText
accessibilityIdentifier = labelText
imageView.image = image
label.sizeToFit()
}
}
Horizontal StackView:
private let topHorizontalStackView: UIStackView = {
let s = UIStackView()
s.distribution = .fillEqually
s.spacing = 10
s.axis = .horizontal
s.alignment = .fill
s.translatesAutoresizingMaskIntoConstraints = false
return s
}()
EDIT I tried to set a height constraint to my LabelWithImage view. Now, It looks ok but when I open the debugger, It says that height is ambiguous for the view.
leftView.layoutIfNeeded() //It is the view with multilineLabel.
view.heightAnchor.constraint(equalToConstant: leftView.bounds.height).isActive = true
What I want shown in screenshot:
EDIT 2 After I give priority to label as @Don said and set compression to low on image view, I got below result. Below code is still active by the way
leftView.layoutIfNeeded() //It is the view with multilineLabel.
view.heightAnchor.constraint(equalToConstant: leftView.bounds.height).isActive = true
If I give specific constant to labelWithImageView as (40 is UIStackView top and bottom insets);
view.heightAnchor.constraint(equalToConstant: leftView.bounds.height - 40).isActive = true
Views inside top vertical UIStackView shows ambitious layout. (You can't see that views inside screenshots because I guess those are not related.)