class BkgTableVC: UITableViewController { let bkgView = TVBkgView() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white tableView.register(UITableViewCell.self, forCellReuseIdentifier: "c") tableView.contentInset = UIEdgeInsets(top: 200, left: 0, bottom: 0, right: 0) tableView.backgroundView = bkgView } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 30 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let c = tableView.dequeueReusableCell(withIdentifier: "c", for: indexPath) c.textLabel?.text = "\(indexPath)" return c } } class TVBkgView: UIView, UICollectionViewDataSource, UICollectionViewDelegate { let titleLabel: UILabel = { let v = UILabel() v.backgroundColor = .brown v.textColor = .yellow v.textAlignment = .center return v }() let infoLabel: UILabel = { let v = UILabel() v.backgroundColor = .brown v.textColor = .yellow v.textAlignment = .center return v }() var cView: UICollectionView! override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init?(coder: NSCoder) { super.init(coder: coder) commonInit() } func commonInit() -> Void { backgroundColor = .orange let fl = UICollectionViewFlowLayout() fl.scrollDirection = .horizontal fl.itemSize = CGSize(width: 160, height: 80) cView = UICollectionView(frame: .zero, collectionViewLayout: fl) titleLabel.translatesAutoresizingMaskIntoConstraints = false cView.translatesAutoresizingMaskIntoConstraints = false infoLabel.translatesAutoresizingMaskIntoConstraints = false addSubview(titleLabel) addSubview(cView) addSubview(infoLabel) NSLayoutConstraint.activate([ titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: 44.0), titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0), titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20.0), titleLabel.heightAnchor.constraint(equalToConstant: 28.0), cView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8.0), cView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0.0), cView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0.0), cView.heightAnchor.constraint(equalToConstant: 88.0), infoLabel.topAnchor.constraint(equalTo: cView.bottomAnchor, constant: 8.0), infoLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0), infoLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20.0), infoLabel.heightAnchor.constraint(equalTo: titleLabel.heightAnchor), ]) titleLabel.text = "Background View" infoLabel.text = "Info" cView.dataSource = self cView.delegate = self cView.register(TVBkgCell.self, forCellWithReuseIdentifier: "c") } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 30 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let c = collectionView.dequeueReusableCell(withReuseIdentifier: "c", for: indexPath) as! TVBkgCell c.label.text = "\(indexPath.item)" c.button.setTitle("Button \(indexPath.item)", for: []) c.callBack = { [weak self] str in guard let self = self else { return } self.infoLabel.text = "Tapped: \(str)" } return c } } class TVBkgCell: UICollectionViewCell { var callBack: ((String) -> ())? let label: UILabel = { let v = UILabel() v.backgroundColor = .yellow v.textAlignment = .center return v }() let button: UIButton = { let v = UIButton() v.backgroundColor = .red v.setTitleColor(.white, for: .normal) v.setTitleColor(.lightGray, for: .highlighted) return v }() override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init?(coder: NSCoder) { super.init(coder: coder) commonInit() } func commonInit() -> Void { contentView.backgroundColor = .systemBlue label.translatesAutoresizingMaskIntoConstraints = false button.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(label) contentView.addSubview(button) let g = contentView.layoutMarginsGuide NSLayoutConstraint.activate([ label.topAnchor.constraint(equalTo: g.topAnchor), label.leadingAnchor.constraint(equalTo: g.leadingAnchor), label.trailingAnchor.constraint(equalTo: g.trailingAnchor), button.topAnchor.constraint(greaterThanOrEqualTo: label.bottomAnchor, constant: 8.0), button.leadingAnchor.constraint(equalTo: g.leadingAnchor), button.trailingAnchor.constraint(equalTo: g.trailingAnchor), button.bottomAnchor.constraint(equalTo: g.bottomAnchor), ]) button.addTarget(self, action: #selector(btnTap(_:)), for: .touchUpInside) } @objc func btnTap(_ sender: UIButton) { if let t = sender.currentTitle { callBack?(t) } } }