[iOS] UITableViewのCellをコードでカスタマイズする

iOSのアプリを開発する場合、UIを作成するのにXibを使ってグラフィカルにUIを組んでいく場合と、ソースコードで全て記述するパターンと2種類の方法があります。
(SwiftUIを使わないパターンを想定しています。)
Xibを使うとグラフィカルにできる一方、Xibファイルが競合する恐れがあります。
ソースコードで全てやる場合は、競合の恐れは少なくなりますが、グラフィカルにできなくなります。

ソースコードでCellをカスタムする場合のポイントをまとめてみます。

Cellのカスタム方法

UITableViewCellのサブクラスを作成して、ベースとなるクラスにします。
(今後AutoLayoutでCellを組んだり、XibでCellを組む際のベースクラスにする)
サブクラスで作成したViewを自分のcontentViewに使いするメソッドを用意しておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// ベースとなるCell
 
/// Common TableViewCell
class AppTableViewCell: UITableViewCell {
 
    var onSelect: (() -> Void) = { }
    var isEnabled: Bool = true
 
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }
 
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        //fatalError("init(coder:) has not been implemented")
    }
 
    /// contentViewにViewを追加して、サイズをAutoLayoytでcontentViewのサイズに合わせます。
    func addToContentView(_ v: UIView) {
        self.contentView.addSubview(v)
        v.setupFitConstraint(to: self.contentView)
    }
 
    override func awakeFromNib() {
        super.awakeFromNib()
    }
 
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
 
}
 
/// Cellをコードでカスタムする際に実装するプロトコル
protocol ICustomCell {
 
    /// Cellの高さを返します
    var cellHeight: CGFloat { get }
 
}

あまり意味がありませんが、LabelのみのCellを作成してみます。
ポイントはCellのViewをUIViewで定義してカスタムしているところと、Cellの縦のサイズを指定しています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/// Labelのみのセル
class SimpleSelectCell: AppTableViewCell, ICustomCell {
 
    var cellHeight: CGFloat = 44.0
 
    let mainView = SimpleSelectCellView()
 
    init(title: String, onSelect: @escaping (() -> Void)) {
        super.init(style: .default, reuseIdentifier: nil)
 
        self.addToContentView(mainView)
 
        self.onSelect = onSelect
        self.title = title
    }
 
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
 
    var title: String {
        get { mainView.titleLabel.text ?? "" }
        set { mainView.titleLabel.text = newValue }
    }
 
}
 
extension SimpleSelectCell {
 
    class SimpleSelectCellView: UIView {
 
        let titleLabel = UILabel()
 
        init() {
            super.init(frame: CGRect())
            setupSubviews()
        }
 
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
 
        func setupSubviews() {
            self.addSubview(titleLabel)
 
            titleLabel.translatesAutoresizingMaskIntoConstraints = false
            titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: common.cellmargin).isActive = true
            titleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -(common.cellmargin)).isActive = true
            titleLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
            titleLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
        }
 
    }
 
}

このCellを使うTableViewではCellの高さを指定してあげる必要があります。
StackViewを使ったり、Xibで作成したCellの場合は高さを自動で判定できるので、UITableView.automaticDimensionが使えます。

1
2
3
4
5
6
7
8
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    let cell = self.tableView(self, cellForRowAt: indexPath)
    if let cell = cell as? ICustomCell {
        return cell.cellHeight
    }
 
    return UITableView.automaticDimension
}

参考URL

0 件のコメント :

コメントを投稿