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)