コードで書くStackViewとAutoLayout

Storyboardでしか書いたことなかったけど、データが動的な場合はコードの方が楽なのでメモ。


import UIKit

class MainViewController : UIViewController {

let listView = ListView()

override func viewDidLoad() {
self.view.addSubview(listView)
listView.translatesAutoresizingMaskIntoConstraints = false
listView.widthAnchor.constraint(equalToConstant: 300).isActive = true
listView.heightAnchor.constraint(equalToConstant: 100).isActive = true
listView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 0).isActive = true
listView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor, constant: 0).isActive = true

let item1 = Item()
let item2 = Item()
let item3 = Item()
stackView.addArrangedSubview(item1)
stackView.addArrangedSubview(item2)
stackView.addArrangedSubview(item3)

}
}

class StackView : UIView {
let stackView = UIStackView()

override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}

func setup(){
self.backgroundColor = UIColor.white

self.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.distribution = .fillEqually
stackView.alignment = .fill
stackView.spacing = 10.0
stackView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
stackView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0).isActive = true
stackView.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true

}
}

class Item : UIView {
let imageView = UIImageView()
let name = UILabel()

override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func setup(){
self.addSubview(imageView)

     imageView.backgroundColor = UIColor.gray
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
imageView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0).isActive = true
imageView.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true

self.addSubview(name)
name.text = "TEST"
name.translatesAutoresizingMaskIntoConstraints = false
name.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
name.rightAnchor.constraint(equalTo: self.rightAnchor, constant:0).isActive = true
name.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 5).isActive = true
name.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
}
}


メモ


  • stackViewにはwidth,heightの指定が必須。指定しないとサイズが0になる

  • Item(StackViewに追加するView)はaddSubViewじゃなくてaddArrangedSubviewで追加する

  • Itemのサイズは指定しないと最小になる。サイズを持つ要素(UILabelとか)の場合はテキスト分のサイズに。ただdistributionalignmentで拡大のルールは決められる。

  • Webでいうflexboxと考え方は一緒。

思ったよりAutoLayoutをコードで書くのがめんどくさくないので今後はコードで書いていきたい。isActive = trueはよく忘れる。