Используя типичный UITableView
, это было достигнуто:
добавив эти строки в viewDidLoad()
:
myTableView.layer.borderColor = myTableView.separatorColor?.cgColor
myTableView.layer.borderWidth = 1.0
myTableView.layer.cornerRadius = 6.0
Редактировать: Другой подход, предусматривающий использование переопределения frame
для придания таблице "вставок".
Добавьте CAShapeLayer
в качестве подслоя к ячейке. Установите его путь к UIBezierPath
, который формирует правильные края и углы.
Верхняя ячейка будет иметь только левый, верхний и правый края (без дна), а верхние углы закруглены.
Средние ячейки будут иметь левый, верхний и правый края (без дна), углы НЕ будут округлены.
Нижняя ячейка будет иметь все 4 ребра с закругленными нижними углами.
В ячейке таблицы с одной строкой будут все 4 ребра, а все 4 угла закруглены.
Результат:
Полный код (IBOutlets не требуется):
enum RoundedTableViewCellType {
case first
case last
case single
case middle
}
class RoundedTableViewCell: UITableViewCell {
var theLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.font = UIFont.systemFont(ofSize: 16.0, weight: .bold)
v.textColor = UIColor(red: 62.0 / 255.0, green: 43.0 / 255.0, blue: 191.0 / 255.0, alpha: 1.0)
return v
}()
private var borderLayer = CAShapeLayer()
private var myType: RoundedTableViewCellType = .middle
override var frame: CGRect {
get {
return super.frame
}
set {
let inset: CGFloat = 20
var frame = newValue
frame.origin.x += inset
frame.size.width -= 2 * inset
super.frame = frame
}
}
var borderColor: UIColor = .clear {
didSet {
borderLayer.strokeColor = borderColor.cgColor
}
}
var borderWidth: CGFloat = 0.0 {
didSet {
borderLayer.lineWidth = borderWidth
}
}
// need to re-set layer cornerRadius if radius is set *after* type (in VC's cellForRowAt)
var radius: CGFloat = 6.0 {
didSet {
type = myType
}
}
var type: RoundedTableViewCellType = .middle {
didSet {
myType = type
switch type {
case .first:
layer.cornerRadius = radius
layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
case .last:
layer.cornerRadius = radius
layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
case .single:
layer.cornerRadius = radius
layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner, .layerMinXMinYCorner, .layerMaxXMinYCorner]
case .middle:
layer.cornerRadius = 0
layer.maskedCorners = []
}
}
}
override func layoutSubviews() {
super.layoutSubviews()
let r = radius
var bPath = UIBezierPath()
let ptTopLeft = CGPoint(x: 0.0, y: 0.0)
let ptTopRight = CGPoint(x: bounds.width, y: 0.0)
let ptBotRight = CGPoint(x: bounds.width, y: bounds.height)
let ptBotLeft = CGPoint(x: 0.0, y: bounds.height)
switch type {
case .first:
// top cell, add left, top and right edges
// round top corners
bPath.move(to: ptBotLeft)
bPath.addLine(to: CGPoint(x: ptTopLeft.x, y: ptTopLeft.y + r))
bPath.addQuadCurve(to: CGPoint(x: ptTopLeft.x + r, y: ptTopLeft.y),
controlPoint: ptTopLeft)
bPath.addLine(to: CGPoint(x: ptTopRight.x - r, y: ptTopRight.y))
bPath.addQuadCurve(to: CGPoint(x: ptTopRight.x, y: ptTopRight.y + r),
controlPoint: ptTopRight)
bPath.addLine(to: CGPoint(x: ptBotRight.x, y: ptBotRight.y))
case .last:
// bottom cell, add all four edges
// round bottom corners
bPath = UIBezierPath(roundedRect: bounds,
byRoundingCorners: [.bottomLeft, .bottomRight],
cornerRadii: CGSize(width: r, height: r))
case .single:
// one-row table, add all four edges
// round all four corners
bPath = UIBezierPath(roundedRect: bounds, cornerRadius: r)
case .middle:
// middle cell, add left, top, right edges
// round NO corners
bPath.move(to: ptBotLeft)
bPath.addLine(to: ptTopLeft)
bPath.addLine(to: ptTopRight)
bPath.addLine(to: ptBotRight)
}
borderLayer.path = bPath.cgPath
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() -> Void {
contentView.addSubview(theLabel)
NSLayoutConstraint.activate([
theLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16.0),
theLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -16.0),
theLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16.0),
theLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16.0),
])
layer.addSublayer(borderLayer)
borderLayer.fillColor = UIColor.clear.cgColor
// default values
borderColor = UIColor(red: 220.0 / 255.0, green: 215.0 / 255.0, blue: 244.0 / 255.0, alpha: 1.0)
borderWidth = 1.0
}
}
class RoundedCornersInsetTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var myTableView: UITableView = {
let v = UITableView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
var theData = [1, 2, 3, 4]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red: 242.0 / 255.0, green: 240.0 / 255.0, blue: 250.0 / 255.0, alpha: 1.0)
myTableView.dataSource = self
myTableView.delegate = self
myTableView.register(RoundedTableViewCell.self, forCellReuseIdentifier: "RoundedTableViewCell")
myTableView.backgroundColor = .clear
myTableView.separatorStyle = .none
myTableView.tableFooterView = UIView(frame: CGRect.zero)
view.addSubview(myTableView)
NSLayoutConstraint.activate([
// constrain top + 40-pts
myTableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40.0),
// constrain leading / trailing to 0.0
myTableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0.0),
myTableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0.0),
// change this as appropriate
myTableView.heightAnchor.constraint(equalToConstant: 400.0)
])
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return theData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RoundedTableViewCell", for: indexPath) as! RoundedTableViewCell
cell.theLabel.text = "Cell \(theData[indexPath.row])"
cell.accessoryType = .disclosureIndicator
if theData.count == 1 {
cell.type = .single
} else {
if indexPath.row == 0 {
cell.type = .first
} else if indexPath.row == theData.count - 1 {
cell.type = .last
} else {
cell.type = .middle
}
}
// configurable cell border properties
//cell.borderColor = UIColor(red: 220.0 / 255.0, green: 215.0 / 255.0, blue: 244.0 / 255.0, alpha: 1.0)
//cell.borderWidth = 2.0
//cell.radius = 16.0
return cell
}
}