UIStackView不改变宽度

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UIStackView不改变宽度相关的知识,希望对你有一定的参考价值。

我有一个UIStackViewUIImageViews可能从1到5.每个UIImageView有一个图像来自一个阵列(从以前下载和缓存的图像),我想保持UIImageViews保持完美的圆形。如果有超过3个图像,我改变widthUIStackView常数以及图像之间的间距以重叠的方式。

我在之前的项目中写过这个代码并且它工作得很好,但由于某种原因,当我调用changeNavStackWidth函数来改变widthUIStackView时,宽度没有更新,我也不知道为什么。

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 }
 }
答案

基于我们在聊天中的讨论。这是你想要的:

A)如果只有一个图像enter image description here B)如果有两个图像:enter image description here C)如果有超过2:enter image description here

码:

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))
            ])

    }
}
另一答案

而不是调整StackView的宽度来调整图像:

  1. 创建一个UIView并将UIImageView作为子视图添加到UIView。
  2. 使用UIView向UIImageView添加topbottom约束
  3. 使用UIView添加带有UIImageView的center horizontally约束
  4. aspect ratio约束添加到UIImageView自身并将该比率设置为1:1
  5. 将UIView添加到堆栈视图

与UIView相关的UIImageView约束将使图像保持相同,并且对自身的宽高比约束将使UIImage保持完美的圆形。

另一答案

将imageView的内容模式更改为.aspectFit也可以完成这一操作,而不必弄乱堆栈的宽度。

将此imageView.contentMode = .scaleAspectFill更改为此imageView.contentMode = .scaleAspectFit

AspectFill拉伸图像以适合视图,并且不保持图像的缩放比例AspectFit拉伸图像,直到水平边界或垂直边界撞击视图,同时保持图像的缩放比例。

here

以上是关于UIStackView不改变宽度的主要内容,如果未能解决你的问题,请参考以下文章

UIStackView 宽度和高度不改变以下元素添加

具有“包装内容”宽度的 UIStackView

Swift 3,iOS 10 - 以编程方式声明 UIStackView 不适合屏幕宽度

为啥图像视图会拉伸以填充 UIStackView 中宽度的一半?

UIStackView:添加相同宽度的排列视图

UIStackView :使用情节提要更改 UIStackView 图像宽度