Reputation: 2537
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.)
Upvotes: 1
Views: 1560
Reputation: 488
Well, it just looks like your constraints are wrong, here I've made an example with screen attached so you can recreate my constraints
Here's an explanation: in left view set your own constraints to fill the view (check for ambiguity since right view is supposed to get the size from the left one), set all labels inside it with vertical content hugging priority to 1000
on right one you simply need to set the title vertical content hugging priority to 1000 (+ basic needed constraints like leading, trailing and top to fill the view) and viola, image will morph into whatever size needed to match left view's size.
Upvotes: 0