在 Swift 4 中以编程方式将 UIImageView、UILabel 添加到 UIStackView

Posted

技术标签:

【中文标题】在 Swift 4 中以编程方式将 UIImageView、UILabel 添加到 UIStackView【英文标题】:Add UIImageView, UILabel to UIStackView programmatically in Swift 4 【发布时间】:2017-11-02 12:54:06 【问题描述】:

我正在尝试创建一组UIImageViewUILabel 并像这样以编程方式添加到UIStackView

var someLetters: [Int: String] = [0:"g",1:"n",2:"d"]

let stackView1 = UIStackView(arrangedSubviews: createLetters(someLetters))
someScrollView.addSubview(stackView1)

func createLetters(_ named: [Int: String]) -> [UIView] 
    return named.map  name in
        let letterImage = UIImageView()
        letterImage.image = UIImage(named: "\(name.key)")

        let letterLabel = UILabel()
        letterLabel.text = name.value

        let subView = UIView()
        subView.addSubview(letterLabel)
        subView.addSubview(letterImage)

        return subView
    

UIStackViews arrangedSubviews 只接受UIView 作为参数 所以我创建了一个额外的UIView 作为UILabelUIImageView 的容器。没有编译错误,但在屏幕上看不到任何 UI 元素。

我在这里做错了什么?

【问题讨论】:

尝试添加宽度和高度约束。一旦我也面临这个问题 您需要为 stackView1 添加约束并告诉 stackView1 它将如何安排添加到其中的视图(我认为对于您的情况,它可以平均分配)。 UILabelUIImageViewUIView 的子类 - 您可以将它们直接添加到 UIStackView - 无需包装它们。 这是不正确。您可以将UIView 的任何子类添加到a UIStackView。当您尝试添加UILabel 时会发生什么?你看到了什么错误? @AshleyMills 你是对的。将UILabel 传递给UIStackView 时,我没有收到任何编译错误。不知道为什么它在我第一次尝试时不接受UILabel。谢谢。 【参考方案1】:

添加一些约束

 stackView1.alignment = .center
        stackView1.distribution = .fillEqually
        stackView1.axis = .vertical
        stackView1.spacing = 10.0
        stackView1.translatesAutoresizingMaskIntoConstraints = false

        let leading = NSLayoutConstraint(item: stackView1, attribute: .leading, relatedBy: .equal, toItem: someScrollView, attribute: .leading, multiplier: 1, constant: 5)
        let trailing = NSLayoutConstraint(item: stackView1, attribute: .trailing, relatedBy: .equal, toItem: someScrollView, attribute: .trailing, multiplier: 1, constant: 5)

        let height = NSLayoutConstraint(item: stackView1, attribute: .height, relatedBy: .equal, toItem: someScrollView, attribute: .height, multiplier: 0.8, constant: 50)

        let alignInCenter = NSLayoutConstraint(item: stackView1, attribute: .centerX, relatedBy: .equal, toItem: someScrollView, attribute: .centerX, multiplier: 1, constant: 1)
        let alignInCenterY = NSLayoutConstraint(item: stackView1, attribute: .centerY, relatedBy: .equal, toItem: someScrollView, attribute: .centerY, multiplier: 1, constant: 1)

        someScrollView.addSubview(stackView1)
        NSLayoutConstraint.activate([alignInCenter,alignInCenterY,leading, trailing, height])

并且还给字母和ImageView添加了一些约束

 func createLetters(_ named: [Int: String]) -> [UIView] 
        return named.map  name in
            let letterImage = UIImageView()
            letterImage.image = UIImage(named: "\(name.key)")
            letterImage.backgroundColor = UIColor.gray


            let letterLabel = UILabel()
            letterLabel.text = name.value
            letterLabel.backgroundColor = UIColor.green

            let stackView = UIStackView(arrangedSubviews: [letterLabel, letterImage])
            stackView.alignment = .center
            stackView.distribution = .fillEqually
            stackView.axis = .horizontal
            let widht = NSLayoutConstraint(item: letterImage, attribute: NSLayoutAttribute.width, relatedBy: .equal, toItem: stackView, attribute: .width, multiplier: 1, constant: 100)
            let height = NSLayoutConstraint(item: letterImage, attribute: NSLayoutAttribute.height, relatedBy: .equal, toItem: stackView, attribute: .height, multiplier: 1, constant: 100)
            NSLayoutConstraint.activate([widht, height])
            return stackView
        
    

但我不确定您在 stackView 中寻找的轴和分布类型。此代码缺少一些约束,因此您必须识别并添加它们,以便布局中没有歧义

【讨论】:

【参考方案2】:

首先,尝试将UILabels 和UIImageViews 添加到情节提要中的堆栈视图。在这里您可以看到我正在使用包含在垂直堆栈视图中的水平堆栈视图。从这里您可以看到在代码中创建相同的约束时需要使用的约束。

【讨论】:

【参考方案3】:

更新代码为:

func createLetters(_ named: [Int: String]) -> [UIView] 返回named.map 名称在 让 letterImage = UIImageView(frame: CGRect(x: 0, y: name.key*10, width: 20, height: 20)) letterImage.image = UIImage(named: "(name.key)") letterImage.backgroundColor = .green

        let letterLabel = UILabel(frame: CGRect(x: 30, y: name.key*10, width: 20, height: 20))
        letterLabel.text = name.value
        letterLabel.backgroundColor = .red

        let stackView   = UIStackView(frame: CGRect(x: 0, y:name.key*30, width: 100, height: 50))
        stackView.axis  = UILayoutConstraintAxis.vertical
        stackView.distribution  = UIStackViewDistribution.equalSpacing
        stackView.alignment = UIStackViewAlignment.center
        stackView.spacing   = 16.0

        stackView.addArrangedSubview(letterImage)
        stackView.addArrangedSubview(letterLabel)

        return stackView
    

这将返回 3 个堆栈视图,因为 someLetters 数组计数为 3。将其称为

self.tview.addSubview(createLetters(someLetters)[0])
self.tview.addSubview(createLetters(someLetters)[1])
self.tview.addSubview(createLetters(someLetters)[2])

如果您只获得一个堆栈视图标签和具有相同代码的图像,则只传递一个参数。

【讨论】:

以上是关于在 Swift 4 中以编程方式将 UIImageView、UILabel 添加到 UIStackView的主要内容,如果未能解决你的问题,请参考以下文章

如何在Swift中以编程方式从另一个图像中剪切徽标的形状(png图像)?

如何在 ios 4 中以编程方式将图像数组添加到 Imageview?

如何在 Swift 4 中以编程方式注册 UITableViewHeaderFooterView?

使用 Cocoa 在 Swift 4.0 中以编程方式创建复选框的标准方法是啥?

如何在 Swift 中以编程方式将 UILabel 对象居中?

在 UIImage 上添加 TextViews - Swift - 以编程方式