UITableViewにCustomCellゴテゴテで実装された画面を、UIScrollViewに置き換える機会がありましたので共有します。
主にUIStackViewへの追加で制約が入らなくてつまりました。
※UITableViewCellをそのまま使う前提で書いてます。
普通にViewを置く場合はもっと簡単にできると思います。
前説
まずUITableViewCellってコードから生成できるの…?
というところから始まりました。
途中、
制約全然効いてくれない!!
セルの高さが全部同じになっちゃう!!
横幅がおかしくなる!!!
とか色々やりながら、結果生まれたのが以下のコードです。
その結果生まれたのが以下のコードです。
コードとストーリーボードの例
ViewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var stack: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let row = 20
for i in 0...row {
let cell = Cell.init(style: .default, reuseIdentifier: "Cell", widht: self.stack.frame.width)
cell.heightAnchor.constraint(equalToConstant: cell.frame.height).isActive = true
cell.hogeLabel.text = "\(i)"
print("add to stack:\(cell)")
self.stack.addArrangedSubview(cell)
}
}
}
Cell.swift
import UIKit
class Cell:UITableViewCell {
// セルにはラベル1つだけおいてある
@IBOutlet weak var hogeLabel: UILabel!
// ストーリーボードで配置した時の初期化処理※ストーリーボードからの初期化は想定してません
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.nibInit(width: 0.0)
}
// 横幅を受け取って初期化する(制約がうまく効かなかったので)
init(style: UITableViewCell.CellStyle, reuseIdentifier: String?, widht:CGFloat) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.nibInit(width: widht)
}
// viewの初期化
fileprivate func nibInit(width: CGFloat) {
guard let view = UINib(nibName: "Cell", bundle: nil)
.instantiate(withOwner: self, options: nil)
.first as? UIView else { return }
//セルの高さはセル側でランダムに決める※使うときはちゃんとConstとか作って高さ設定してね
let height = Bool.random() ? 50:100
view.frame = CGRect(x: 0, y: 0, width: width, height: CGFloat(height))
self.frame = CGRect(x: 0, y: 0, width: width, height: CGFloat(height))
self.addSubview(view)
}
}
ストーリーボードは特に特別な設定はしておりません。
普通にScrollViewをおいて中にStackViewを配置するだけです。
スクロールビューについては(多分)いちばんシンプルなUIScrollViewの実装を見てみてください。
**もっとこんな方法あるよ!!**や、
**ここちょっとやばいよ!!**などございましたらお教えいただけますと幸いです。
ありがとうございました。