swift UITableView
UITableView是我们开发过程中比较常用的,用于显示一系列对象,UITableView继承自UIScrollView,UIScrollView可以在任意方向滑动,而UITableView只在垂直方向上滑动。UITableView中的内容是由UITableViewCell负责显示的。
UITableView的内容有UITableViewCell来显示。创建UITableViewCell的时候,可以自定义Cell也可以使用系统自带的样式,系统的样式有4种
.value1 包含一个左侧的可选视图和一个左对齐的标签对象,在单元格右侧还有一个灰色、右对齐的标签对象。
截屏2021-01-25 上午11.21.04.png.value2 包含一个左侧、右对齐的蓝色文字标签对象和一个右侧的左对齐的标签对象。
截屏2021-01-25 上午11.21.40.png.default 包含一个左侧的可选图像视图,和一个左对齐的标签对象。
截屏2021-01-25 上午11.23.05.png.subtitle 包含一个左侧的可选图像视图,和一个左对齐的标签对象,在这个标签对象下方,还有一个字体较小的标签对象。
截屏2021-01-25 上午11.23.30.png创建一个UITableView
设置代理
UIViewController,UITableViewDataSource,UITableViewDelegate
var listTableView = UITableView()
// 初始化UITableView style有两种 plain 和grouped,在Cell不能填满屏幕的情况下选用grouped,不会再空白处出现分割线
listTableView = UITableView(frame: view.bounds, style: .grouped)
view.addSubview(listTableView)
listTableView.mas_makeConstraints { (make) in
make?.left.mas_equalTo()(0)
make?.top.equalTo()(view.mas_top)?.offset()(CGFloat(topSafeAreaHeight))
make?.width.mas_equalTo()(kScreenWidth)
make?.bottom.mas_equalTo()(-bottomSafeAreaHeight)
}
// 设置代理
listTableView.delegate = self
listTableView.dataSource = self
listTableView.backgroundColor = .white
实现tableView的代理方法
//MARK: 章节的个数
func numberOfSections(in tableView: UITableView) -> Int {
return 6
}
//MARK: 每一个章节的标题
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return keys[section]
}
//MARK: 设置索引序列内容
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return keys
}
// cell的行数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
// 列表的内容
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellid = "testCellID"
var cell = tableView.dequeueReusableCell(withIdentifier: cellid)
if cell==nil {
cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellid)
}
cell?.textLabel?.text = "标题"
cell?.detailTextLabel?.text = "内容"
cell?.imageView?.image = UIImage(named:"bfship")
return cell!
}
// 设置cell高度
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 70.0
}
// 选中cell后执行此方法
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath.row)
}
自定义cell
创建UITableViewCell
截屏2021-01-25 下午2.45.41.png 截屏2021-01-25 下午2.45.36.pngvar userLabel:UILabel! // 名字
var birthdayLabel:UILabel! // 出生日期
var sexLabel:UILabel! // 性别
//添加实例化方法
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// 名字
userLabel = UILabel(frame: CGRect(x: 74, y: 18, width: 70, height: 15))
userLabel.textColor = UIColor.black
userLabel.font = UIFont.boldSystemFont(ofSize: 15)
userLabel.textAlignment = .left
// 性别
sexLabel = UILabel(frame: CGRect(x: 150, y: 20, width: 50, height: 13))
sexLabel.textColor = UIColor.black
sexLabel.font = UIFont.systemFont(ofSize: 13)
sexLabel.textAlignment = .left
// 出生日期
birthdayLabel = UILabel(frame: CGRect(x: 74, y: 49, width: width-94, height: 13))
birthdayLabel.textColor = UIColor.gray
birthdayLabel.font = UIFont.systemFont(ofSize: 13)
birthdayLabel.textAlignment = .left
contentView.addSubview(userLabel)
contentView.addSubview(sexLabel)
contentView.addSubview(birthdayLabel)
}
然后在swift文件里面调用
var dataSource = [[String:String]()]//定义数据容器
dataSource = [["type":"no","name":"张三","sex":"男","icon":"my_def_photo","birthday":"2017-10-11"],
["type":"no","name":"李四","sex":"男","icon":"my_def_photo","birthday":"2011-12-30"],
["type":"no","name":"王五","sex":"女","icon":"my_def_photo","birthday":"2014-9-10"],
["type":"no","name":"JIM","sex":"赵六","icon":"my_def_photo","birthday":"2008-10-1"]]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
修改代理方法,给cell赋值
// 列表的内容
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellid = "testCellID"
var cell:DemoTableViewCell? = tableView.dequeueReusableCell(withIdentifier: cellid) as? DemoTableViewCell
if cell==nil {
cell = DemoTableViewCell(style: .subtitle, reuseIdentifier: cellid)
}
let dict:Dictionary = dataSource[indexPath.row]
cell?.userLabel.text = dict["name"]
cell?.sexLabel.text = dict["sex"]
cell?.birthdayLabel.text = dict["birthday"]
return cell!
}
cell的选择和取消选择
首先定义了一个数据源,因为是单选,所以用的是数组嵌套字典,key就是支付方式,value是代表是否选中个状态的string,如果选中,就把数据源里这个位置的value变成select,但是只能单选,所以还需要把其他的都变成no。
cell的实例化和复用代理方法中,可以看到,如果数据源里的value是selecrt,就把 accessoryType属性设置成checkmark。
tableView(_:, didSelectRowAt:)方法中,可以看到,用For循环来修改元数据中选中状态的value,然后调用reloadData()方法刷新cell。
cell的accessoryType属性的值是枚举UITableViewCellAccessoryType:
有以下5种样式
none 没有任何的样式
detailButton 右侧蓝色的圆圈,中间带叹号
detailDisclosureButton 右侧蓝色圆圈带叹号,它的右侧还有一个灰色向右的箭头
disclosureIndicator 右侧一个灰色的向右箭头
checkmark 右侧蓝色对号
cell = DemoTableViewCell(style: .subtitle//设置style
, reuseIdentifier: cellid)
用数据源中 的type来判断是否选择
// 选中cell后执行此方法
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath.row)
var i = 0
for var dict in dataSource {
if i == indexPath.row {
dict.updateValue("select", forKey: "type")
dataSource[i] = dict
} else {
dict.updateValue("no", forKey: "type")
dataSource[i] = dict
}
i = i+1
}
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellid = "testCellID"
var cell:DemoTableViewCell? = tableView.dequeueReusableCell(withIdentifier: cellid) as? DemoTableViewCell
if cell==nil {
cell = DemoTableViewCell(style: .subtitle, reuseIdentifier: cellid)
}
let dict:Dictionary = dataSource[indexPath.row]
cell?.userLabel.text = dict["name"]
cell?.sexLabel.text = dict["sex"]
cell?.birthdayLabel.text = dict["birthday"]
let type = dict["type"]
//判断当前的状态
if type == "select" {
cell?.accessoryType = .checkmark
} else {
// 如果是多选的话注释else中的内容
cell?.accessoryType = .none
}
return cell!
}
cell的插入和删除
插入和删除设计到的两个代理方法:
tableView(_ tableView:, editingStyleForRowAt indexPath:)
确定编辑模式,Add or Delete
tableView(_ tableView:, commit editingStyle:, forRowAt indexPath:)
当执行编辑操作时,调用此方法
和一个开启TableView编辑模式的方法:
setEditing(_ editing:, animated:)
editing: 是否开启编辑状态
animated: 是否有动画效果
//在右上方添加一个编辑按钮
var clickCutton = UIButton()
view.addSubview(clickCutton)
clickCutton.mas_makeConstraints { (make) in
make?.right.equalTo()(view.mas_right)?.offset()(-15)
make?.top.equalTo()(view.mas_top)?.offset()(35)
make?.width.mas_equalTo()(100)
make?.height.mas_equalTo()(30)
}
clickCutton.backgroundColor = .white
clickCutton.setTitle("编辑", for: .normal)
clickCutton.setTitleColor(.black, for: .normal)
clickCutton.addTarget(self, action: #selector(clickCuttonAction), for: .touchUpInside)
// 点击打开关闭编辑模式
@objc func clickCuttonAction() {
listTableView.setEditing(!listTableView.isEditing, animated: true)
}
// insert: 添加操作
// delete: 删除操作
// none: 没有任何操作
//MARK: 编辑模式,增加还是删除
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
// return .delete
return .insert
}
//MARK: 执行编辑操作时,调用此方法
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .insert {
//添加
dataSource.insert(["type":"no","name":"小明","sex":"男","icon":"my_def_photo","birthday":"2017-10-11"], at: indexPath.row)
tableView.insertRows(at: [indexPath], with: .right)
} else {
// 删除
dataSource.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .left)
}
}
//MARK: 修改删除时的文字
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String?{
return "删除"
}
cell位置移动功能
·允许用户拖动位于单元格右侧的排序图标,来重新排序TableView中的单元格。类似于支付宝在选择支付顺序时候的效果
·设置cell是否可移动
·tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath)
·每次移动结束后会调用此方法
tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)
移动功能同样需要开启编辑模式setEditing(_: ,animated:)
//编辑模式选择.none
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .none
}
//MARK: 设置cell是否可移动
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
//MARK: 移动结束后调用此方法
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let data = dataSource[sourceIndexPath.row]
dataSource.remove(at: sourceIndexPath.row)
dataSource.insert(data, at: destinationIndexPath.row)
}