Swift - 实现tableView中section分组圆角效果2(含有分区头、尾的情况)
作者:hangge | 2018-10-26 08:14
上文演示了当 section 没有 header 和 footer 的情况下如何实现圆角效果。本文接着介绍如果有分区头、分区尾的情况下如何实现圆角效果。
(3)MyTableViewCell.swift(自定义单元格)
(4)ViewController.swift(主视图控制器)
一、有 header 和 footer 的情况
1,效果图
(1)tableView 中每个 section 的 header 和 footer 都带有圆角。
(2)同时为了让显示效果更好,每个分区头、分区尾、以及单元格左右两侧还设置了边距,使其与边框保持一定的距离。
2,样例代码
(1)MyTableViewSectionHeader.swift(自定义的分区头)
这里面的工作一个是重写它的 frame 属性方法,实现边距效果。二是通过遮罩,实现圆角效果。
import UIKit //自定义分区头 class MyTableViewSectionHeader: UIView { //标题文本标签 var titleLabel:UILabel! //圆角半径 let cornerRadius:CGFloat = 15.0 //实现圆角的遮罩层 var shapeLayer:CAShapeLayer! override init(frame: CGRect) { super.init(frame: frame) //设置背景色 self.backgroundColor = UIColor.black //设置文本标签 titleLabel = UILabel() titleLabel.text = "self.adHeaders?[section]" titleLabel.textColor = UIColor.white titleLabel.sizeToFit() titleLabel.center = CGPoint(x: self.frame.width/2, y: 20) titleLabel.textAlignment = .center self.addSubview(titleLabel) //设置圆角遮罩 shapeLayer = CAShapeLayer() self.layer.mask = shapeLayer } //覆盖frame,自动添加边距 override var frame: CGRect { get { return super.frame } set { var frame = newValue frame.origin.x += 15 frame.origin.y += 10 frame.size.width -= 2 * 15 frame.size.height -= 10 super.frame = frame } } //子视图布局 override func layoutSubviews() { super.layoutSubviews() //调整文字标签位置 self.titleLabel.frame = CGRect(x: 0, y:0, width:self.frame.width, height:self.frame.height) //调整遮罩层路径 let bezierPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: cornerRadius, height: cornerRadius)) shapeLayer.path = bezierPath.cgPath } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
(2)MyTableViewSectionFooter.swift(自定义的分区尾)
里面做的工作和上面一样,一是重写它的 frame 属性方法,实现边距效果。二是通过遮罩,实现圆角效果。
import UIKit //自定义分区尾 class MyTableViewSectionFooter: UIView { //标题文本标签 var titleLabel:UILabel! //圆角半径 let cornerRadius:CGFloat = 15.0 //实现圆角的遮罩层 var shapeLayer:CAShapeLayer! override init(frame: CGRect) { super.init(frame: frame) //设置背景色 self.backgroundColor = UIColor.darkGray //设置文本标签 titleLabel = UILabel() titleLabel.text = "self.adHeaders?[section]" titleLabel.textColor = UIColor.white titleLabel.sizeToFit() titleLabel.center = CGPoint(x: self.frame.width/2, y: 20) titleLabel.font = UIFont.systemFont(ofSize: 15) self.addSubview(titleLabel) //设置圆角遮罩 shapeLayer = CAShapeLayer() self.layer.mask = shapeLayer } //覆盖frame,自动添加边距 override var frame: CGRect { get { return super.frame } set { var frame = newValue frame.origin.x += 15 frame.size.width -= 2 * 15 frame.size.height -= 10 super.frame = frame } } //子视图布局 override func layoutSubviews() { super.layoutSubviews() //调整文字标签位置 self.titleLabel.frame = CGRect(x: 10, y:0, width:self.frame.width-10, height:self.frame.height) //调整遮罩层路径 let bezierPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.bottomLeft,.bottomRight], cornerRadii: CGSize(width: cornerRadius, height: cornerRadius)) shapeLayer.path = bezierPath.cgPath } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
(3)MyTableViewCell.swift(自定义单元格)
代码很简单,只需重写它的 frame 属性方法,实现边距效果即可。
import UIKit //自定义单元格 class MyTableViewCell: UITableViewCell { override var frame: CGRect { get { return super.frame } set { var frame = newValue frame.origin.x += 15 frame.size.width -= 2 * 15 super.frame = frame } } }
(4)ViewController.swift(主视图控制器)
最后只需要让 tableView 使用我们自定义的分区头、分区尾、单元格即可。
import UIKit class ViewController: UIViewController , UITableViewDelegate, UITableViewDataSource{ var tableView:UITableView? var allnames:Dictionary<Int, [String]>? override func loadView() { super.loadView() } override func viewDidLoad() { super.viewDidLoad() //初始化数据 self.allnames = [ 0:[String]([ "UILabel 标签", "UITextField 文本框"]), 1:[String]([ "UIDatePiker 日期选择器", "UIToolbar 工具条"]), 2:[String]([ "UIProgressView 进度条"]) ] //创建表视图 self.tableView = UITableView(frame:self.view.frame, style:.grouped) self.tableView!.delegate = self self.tableView!.dataSource = self //创建一个重用的单元格 self.tableView!.register(MyTableViewCell.self, forCellReuseIdentifier: "cell") self.view.addSubview(self.tableView!) } //返回分区 func numberOfSections(in tableView: UITableView) -> Int { return self.allnames!.count } //返回表格行数(也就是返回控件数) func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { let data = self.allnames?[section] return data!.count } //返回分区头部视图 func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let headerView = MyTableViewSectionHeader() headerView.titleLabel.text = "分组\(section)" return headerView } //返回分区头部高度 func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 40 } //返回分区尾部视图 func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { let data = self.allnames?[section] let footerView = MyTableViewSectionFooter() footerView.titleLabel.text = "有\(data!.count)个控件" return footerView } //返回分区尾部高度 func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { return 40 } //创建各单元显示内容(创建参数indexPath指定的单元) func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //获取单元格 let cell = self.tableView?.dequeueReusableCell(withIdentifier: "cell") as! MyTableViewCell cell.accessoryType = .disclosureIndicator //设置单元格内容 let secno = indexPath.section var data = self.allnames?[secno] cell.textLabel?.text = data![indexPath.row] return cell } }
附:只有header、或只有 footer 的情况
有时我们的表格可能只有分区头,或者分区尾,那么要实现圆角效果的话,就需要结合上一篇文章来实现。
1,效果图
(1)tableView 中每个 section 只有 header 没有 footer。
(2)同样地,每个 section 都具有圆角效果。即每个分区头上方两个角,以及该分区最后一个单元格下方两个角都是圆角的。
(3)同时为了让显示效果更好,每个分区头、以及单元格左右两侧还设置了边距,使其与边框保持一定的距离。
2,样例代码
(1)首先我们同样是要自定义分区头(MyTableViewSectionHeader)和单元格(MyTableViewCell)。具体代码和上面一样,这里就不再重复了。
(2)不同之处主视图控制器(ViewController)这边,除了使用我们自定义的分区头和单元格外, 还要在 cellForRowAt 方法中,对每个 section 最后一个单元格设置圆角遮罩。
import UIKit class ViewController: UIViewController , UITableViewDelegate, UITableViewDataSource{ var tableView:UITableView? var allnames:Dictionary<Int, [String]>? override func loadView() { super.loadView() } override func viewDidLoad() { super.viewDidLoad() //初始化数据 self.allnames = [ 0:[String]([ "UILabel 标签", "UITextField 文本框"]), 1:[String]([ "UIDatePiker 日期选择器", "UIToolbar 工具条"]), 2:[String]([ "UIProgressView 进度条"]) ] //创建表视图 self.tableView = UITableView(frame:self.view.frame, style:.grouped) self.tableView!.delegate = self self.tableView!.dataSource = self //创建一个重用的单元格 self.tableView!.register(MyTableViewCell.self, forCellReuseIdentifier: "cell") self.view.addSubview(self.tableView!) } //返回分区 func numberOfSections(in tableView: UITableView) -> Int { return self.allnames!.count } //返回表格行数(也就是返回控件数) func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { let data = self.allnames?[section] return data!.count } //返回分区头部视图 func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let headerView = MyTableViewSectionHeader() headerView.titleLabel.text = "分组\(section)" return headerView } //返回分区头部高度 func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 40 } //创建各单元显示内容(创建参数indexPath指定的单元) func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //获取单元格 let cell = self.tableView?.dequeueReusableCell(withIdentifier: "cell") as! MyTableViewCell cell.accessoryType = .disclosureIndicator //设置单元格内容 let secno = indexPath.section var data = self.allnames?[secno] cell.textLabel?.text = data![indexPath.row] //圆角半径 let cornerRadius:CGFloat = 15.0 //下面为设置圆角操作(通过遮罩实现) let sectionCount = tableView.numberOfRows(inSection: indexPath.section) let shapeLayer = CAShapeLayer() cell.layer.mask = nil //如果是最后一个单元格则设置圆角遮罩 if indexPath.row == sectionCount - 1 { var bounds = cell.bounds bounds.size.height -= 1.0 //这样每一组尾行底部分割线不显示 let bezierPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.bottomLeft,.bottomRight], cornerRadii: CGSize(width: cornerRadius,height: cornerRadius)) shapeLayer.path = bezierPath.cgPath cell.layer.mask = shapeLayer } return cell } }
全部评论(0)