UIStackView not changing the width

UIStackView not changing the width



I have a UIStackView with UIImageViews that might be from 1 to 5. Each UIImageView has an image coming from an array (from previously downloaded and cached images) and I'd like to keep the UIImageViews stay in a perfect circle. I change the width constant of the UIStackView along with the spacing between the images in a way to overlap if there are more than 3 images.


UIStackView


UIImageViews


UIImageView


UIImageView


width


UIStackView



I had writen this code in a previous project and it works perfectly fine, but for some reason, when I call the changeNavStackWidth function to change the width of the UIStackView, the width is not being updated and I have no clue why.


changeNavStackWidth


width


UIStackView


var userImages = [String]()

var navStackView : UIStackView =
let stack = UIStackView()
stack.axis = .horizontal
stack.alignment = .fill
stack.distribution = .fillEqually
stack.translatesAutoresizingMaskIntoConstraints = false
return stack
()
override func viewDidLoad()
super.viewDidLoad()
setupNavStack()
navBarStackTapGesture()


func setupNavStack()
guard let navController = navigationController else return

navController.navigationBar.addSubview(navStackView)
// x, y, w, h
navStackView.widthAnchor.constraint(equalToConstant: 95).isActive = true
navStackView.centerYAnchor.constraint(equalTo: navController.navigationBar.centerYAnchor).isActive = true
navStackView.heightAnchor.constraint(equalToConstant: 35).isActive = true
navStackView.centerXAnchor.constraint(equalTo: navController.navigationBar.centerXAnchor).isActive = true



func setNavBarImages()

for image in userImages
let imageView = UIImageView()
// imageView.image = UIImage(named: image)

let photoURL = URL(string: image)
imageView.sd_setImage(with: photoURL)

imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.borderWidth = 1
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true

navStackView.addArrangedSubview(imageView)
navStackView.layoutIfNeeded()


switch userImages.count
case 0:
print("0 images")
case 1:
changeNavStackWidth(constant: 35, spacing: 0)
//changeNavStackWidth(constant: 60, spacing: 0)
case 2:
changeNavStackWidth(constant: 80, spacing: 10)
case 3:
changeNavStackWidth(constant: 95, spacing: -5)
case 4:
changeNavStackWidth(constant: 110, spacing: -10)
case 5:
changeNavStackWidth(constant: 95, spacing: -20)
case 6...1000:
// changeNavStackWidth(constant: 95, spacing: -20)
default:
print("default")


navigationItem.titleView = navStackView
navStackView.layoutIfNeeded()


func changeNavStackWidth(constant: CGFloat, spacing: CGFloat)
navStackView.constraints.forEach constraint in
if constraint.firstAttribute == .width
constraint.constant = constant
print("constan is:", constant) // not being printed


navStackView.spacing = spacing

override func viewDidLayoutSubviews()
super.viewDidLayoutSubviews()
navStackView.subviews.forEach $0.layer.cornerRadius = $0.frame.height / 2






where did you set navStackView.translatesAutoresizingMaskIntoConstraints = false

– Sahil Manchanda
Sep 14 '18 at 18:35







@SahilManchanda in the declaration of the navStackView (I've added it in the code to make it clear)

– Bold Lion
Sep 14 '18 at 18:37


navStackView






Can you check if your changeNavStackWidth function is getting called

– Sahil Manchanda
Sep 14 '18 at 18:43






@SahilManchanda I did, I've put a breakpoint on it and it's called, but for some reason it doesn't iterate through the constraints and I don't know why. When I step into it, it goes into the declaration of navStackView then goes back in the function straight to navStackView.spacing = spacing and doesn't loop through the constraints. This is why that print statement is never executed.

– Bold Lion
Sep 14 '18 at 18:46



navStackView


navStackView.spacing = spacing


print






if possible can you put minimum working code in the question so that i can paste and run.. it will help in debug

– Sahil Manchanda
Sep 14 '18 at 18:52




3 Answers
3



based on our discussion in chat. Here is what you want:



A) if there is only one Image
enter image description here
B) if there are two Images:
enter image description here
C) if there are more than 2:
enter image description here



Code:


import UIKit

class TestStack: UIViewController
var userImages = [#imageLiteral(resourceName: "images-1"),#imageLiteral(resourceName: "images-2"),#imageLiteral(resourceName: "images-4"),#imageLiteral(resourceName: "images-5")]

let imagesHolder: UIView =
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
()

override func viewDidLoad()
super.viewDidLoad()
userImages.removeLast(2)
guard let bar = navigationController?.navigationBar else return
bar.addSubview(imagesHolder)
let size = 25
for i in 0..<userImages.count
var x = i * size
x = userImages.count > 2 ? x/2 : x
x = (i == 1 && userImages.count == 2) ? x + 5 : x
let imageView = UIImageView(frame: CGRect(x: x, y: 0, width: size, height: size))
imageView.image = userImages[i]
imageView.clipsToBounds = true
imageView.layer.cornerRadius = CGFloat(size / 2)
imagesHolder.addSubview(imageView)


let width = CGFloat((userImages.count * size)/2)
NSLayoutConstraint.activate([
imagesHolder.centerYAnchor.constraint(equalTo: bar.centerYAnchor),
imagesHolder.centerXAnchor.constraint(equalTo: bar.centerXAnchor),
imagesHolder.widthAnchor.constraint(equalToConstant: width),
imagesHolder.heightAnchor.constraint(equalToConstant: CGFloat(size))
])








Excellent! Thank you again!

– Bold Lion
Sep 14 '18 at 20:23



Instead of adjusting the StackView's width to adjust to the images:


top


bottom


center horizontally


aspect ratio


1:1



The constraints on the UIImageView in relation to the UIView will keep the images separated out equally, and the aspect ratio constraint on itself will keep the UIImage as a perfect circle.






What about the UIView constraints? Should they be top, bottom, leading & trailing to the UIStackView? (PS: keep in mind, this UIStackView is placed in the middle of the UINavigationBar)

– Bold Lion
Sep 14 '18 at 19:56


UIView


top


bottom


leading


trailing


UIStackView


UIStackView


UINavigationBar






Just top and bottom constraints to the UIStackView. Leading/Trailing constraints and widths of views are based on your settings of the StackView (width, spacing, etc.)

– BlondeSwan
Sep 15 '18 at 1:11


top


bottom



Changing your imageView's content mode to .aspectFit will also do the trick without having to mess with your stackView's width.


.aspectFit



Change this imageView.contentMode = .scaleAspectFill to this imageView.contentMode = .scaleAspectFit


imageView.contentMode = .scaleAspectFill


imageView.contentMode = .scaleAspectFit



AspectFill stretches the image to fit the view, and doesn't maintain the scale ratio of the image
AspectFit stretches the image until the horizontal bound OR vertical bound hits the view, while maintaining the scale ratio of the image.


AspectFill


AspectFit



see here






The problem with this is that I cannot set the image to be a circle. Since the UIImageView is set dynamically, I have to create a new one for each image, but while doing so, the frame is still not set, so I cant get the frame.height / 2. I went through that issue today. This is why I overrride viewDidLayoutSubviews(), iterate through the subviews of the navStackView and then set it.

– Bold Lion
Sep 14 '18 at 19:17


UIImageView


frame.height / 2


viewDidLayoutSubviews()


navStackView






Okay, I was thinking your actual image was a circle. In that case, check out the other answer I posted. You won't need to mess with the width of the StackView if you implement it that way.

– BlondeSwan
Sep 14 '18 at 19:27



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)