コードで書くStackViewとAutoLayout

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


```swift
 
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とか）の場合はテキスト分のサイズに。ただ`distribution `と`alignment`で拡大のルールは決められる。
- Webでいうflexboxと考え方は一緒。

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