简体   繁体   中英

Add UIImageView, UILabel to UIStackView programmatically in Swift 4

I'm trying to create a set of UIImageView , UILabel and add to UIStackView programmatically like so.

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

UIStackView s arrangedSubviews only accepts UIView as a parameter so I created an additional UIView as a container of UILabel and UIImageView . No compile error but not seeing any UI elements on a screen.

What am I doing wrong here?

Add some constraints to

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

and also add some constraints to letters and 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
        }
    }

But I am not sure what axis and what kind of distribution you are looking for in stackView. This code has some of the constraints missing so you have to identify and add them so there is no ambiguity in layouts

As a starting point, try adding the UILabel s and UIImageView s to stack views in a storyboard. Here you can see I'm using horizontal stack views contained in a vertical stack view. From here you can see the constraints you'll need to use to create the same in code.

在此处输入图片说明

Update code as:

func createLetters(_ named: [Int: String]) -> [UIView] { return named.map { name in let 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
    }
}

This will return 3 stack views as someLetters array count is 3. call it as

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

if you to get only one stack view label and image with same code then pass only one parameter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM