Open popeyelau opened 5 years ago
import UIKit class SectionHeader: UITableViewHeaderFooterView { lazy var shapeLayer: CAShapeLayer = CAShapeLayer() let cornerRadius: CGFloat = 10 let inset: CGFloat = 10 override init(reuseIdentifier: String?) { super.init(reuseIdentifier: reuseIdentifier) setup() } func setup() { backgroundView = UIView(frame: bounds) backgroundView?.backgroundColor = .black layer.mask = shapeLayer } override var frame: CGRect { get { return super.frame } set { var frame = newValue frame.origin.x += inset frame.origin.y += inset frame.size.width -= inset * 2 frame.size.height -= inset super.frame = frame } } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() let bezierPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: cornerRadius, height: cornerRadius)) shapeLayer.path = bezierPath.cgPath } } class TableViewCell: UITableViewCell { let inset: CGFloat = 10 override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) backgroundColor = .lightGray } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override var frame: CGRect { get { return super.frame } set { var frame = newValue frame.origin.x += inset frame.size.width -= inset * 2 super.frame = frame } } } class ViewController: UIViewController { lazy var tableView: UITableView = { let tableView = UITableView(frame: view.bounds, style: .grouped) tableView.register(TableViewCell.self, forCellReuseIdentifier: "cell") tableView.register(SectionHeader.self, forHeaderFooterViewReuseIdentifier: "header") tableView.tableFooterView = UIView() tableView.dataSource = self tableView.delegate = self tableView.translatesAutoresizingMaskIntoConstraints = false return tableView }() override func viewDidLoad() { super.viewDidLoad() view.addSubview(tableView) tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true } } extension ViewController: UITableViewDataSource, UITableViewDelegate { func numberOfSections(in tableView: UITableView) -> Int { return 3 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 5 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = "\(indexPath.section) - \(indexPath.row)" cell.accessoryType = .disclosureIndicator return cell } func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { let numberOfRowInSection = self.tableView(tableView, numberOfRowsInSection: indexPath.section) guard indexPath.row == numberOfRowInSection - 1 else { cell.layer.mask = nil return } let shapeLayer = CAShapeLayer() var bounds = cell.bounds bounds.size.height -= 1 let bezierPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 10, height: 10)) shapeLayer.path = bezierPath.cgPath cell.layer.mask = shapeLayer } func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { guard let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "header") else { return nil } return header } func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 60 } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 40 } }