Swift - 表格section header增加滑动删除功能(删除该分区下所有cell)
作者:hangge | 2017-10-25 08:10
我们知道 UITableView 的单元格自带滑动删除功能,设置后只要在单元格 cell 上向左滑动,右侧就会自动出现删除按钮,如下图:
但这样一次只能删除一条记录,不能批量删除。我们可以通过自定义表格的分组头(section header),在其上面增加滑动删除功能,这样滑动分组头时就可以删除该 section 下所有的单元格。
1,效果图
- 在分区头部(section header)上向左滑动,右侧会出现一个“全部删除”按钮。向右滑动又会隐藏删除按钮。这两个过程都是有动画效果的。
- 点击“全部删除”按钮,可以将其所在的整个分区数据删除。
注意:建议使用真机进行调试,模拟器运行时会出现只有一个分区头可以滑动删除的问题。
2,样例代码
(1)SwipeableSectionHeader.swift(自定义的滑动分区头)
import UIKit //自定义滑动分区头代理协议 protocol SwipeableSectionHeaderDelegate{ //删除分区 func deleteSection(section: Int) } //自定义滑动分区头 class SwipeableSectionHeader: UIView { //分区索引 var section:Int = 0 //放置文本标签和按钮的容器 var container:UIView! //标题文本标签 var titleLabel:UILabel! //删除按钮 var deleteButton:UIButton! //代理对象 var delegate:SwipeableSectionHeaderDelegate? //向左滑动手势 var swipeLeft:UISwipeGestureRecognizer! //向右滑动手势 var swipeRight:UISwipeGestureRecognizer! override init(frame: CGRect) { super.init(frame: frame) //背景为黑色 self.backgroundColor = UIColor.black //初始化容器 self.container = UIView() self.addSubview(container) //初始标题文本标签 self.titleLabel = UILabel() self.titleLabel.textColor = UIColor.white self.titleLabel.textAlignment = .center self.container.addSubview(self.titleLabel) //初始化删除按钮 self.deleteButton = UIButton(type: .custom) self.deleteButton.backgroundColor = UIColor(red: 0xfc/255, green: 0x21/255, blue: 0x25/255, alpha: 1) self.deleteButton.setTitle("删除全部", for:.normal) self.deleteButton.titleLabel?.font = UIFont.systemFont(ofSize: 15) self.deleteButton.addTarget(self, action:#selector(buttonTapped(_:)), for:.touchUpInside) self.container.addSubview(self.deleteButton) //向左滑动手势 self.swipeLeft = UISwipeGestureRecognizer(target:self, action:#selector(headerViewSwiped(_:))) self.swipeLeft.direction = .left self.addGestureRecognizer(self.swipeLeft) //向右滑动手势 self.swipeRight = UISwipeGestureRecognizer(target:self, action:#selector(headerViewSwiped(_:))) self.swipeRight.direction = .right self.addGestureRecognizer(self.swipeRight) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } //滑动响应 @objc func headerViewSwiped(_ recognizer:UISwipeGestureRecognizer){ if recognizer.state == .ended { var newFrame = self.container.frame //向左滑动显示出删除按钮,向右滑动隐藏删除按钮 if recognizer.direction == .left { newFrame.origin.x = -self.deleteButton.frame.width }else{ newFrame.origin.x = 0 } //播放动画 UIView.animate(withDuration: 0.25, animations: { ()-> Void in self.container.frame = newFrame }) } } //删除按钮点击 @objc func buttonTapped(_ button:UIButton){ delegate?.deleteSection(section: section) } //子视图布局 override func layoutSubviews() { super.layoutSubviews() self.container.frame = CGRect(x: 0, y:0, width:self.frame.width + 74, height:self.frame.height) self.titleLabel.frame = CGRect(x: 0, y:0, width:self.frame.width, height:self.frame.height) self.deleteButton.frame = CGRect(x: self.frame.size.width, y:0, width:74, height:self.frame.height) } }
(2)ViewController.swift(使用样例)
import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource,UIGestureRecognizerDelegate, SwipeableSectionHeaderDelegate{ var tableView:UITableView! var adHeaders:[String]! var allnames:[[String]]! override func loadView() { super.loadView() } override func viewDidLoad() { super.viewDidLoad() //初始化数据,这一次数据,我们放在属性列表文件里 self.allnames = [["UILabel 标签","UIButton 按钮"], ["UIDatePiker 日期选择器","UITableView 表格视图"], ["UICollectionView 网格"] ] self.adHeaders = [ "常见 UIKit 控件", "中级 UIKit 控件", "高级 UIKit 控件" ] //创建表视图 self.tableView = UITableView(frame:self.view.frame, style:.grouped) self.tableView.delegate = self self.tableView.dataSource = self //创建一个重用的单元格 self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "SwiftCell") self.view.addSubview(self.tableView) } //在本例中,有3个分区 func numberOfSections(in tableView: UITableView) -> Int { return self.adHeaders.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 = SwipeableSectionHeader() //设置代理 headerView.delegate = self //设置标题 headerView.titleLabel.text = self.adHeaders[section] //设置分区索引 headerView.section = section //设置手势优先级(否则将与表格自带的手势冲突,造成滑动分区头时出现第一个cell的删除按钮) if let gestureRecognizers = tableView.gestureRecognizers { for recognizer in gestureRecognizers { recognizer.require(toFail: headerView.swipeLeft) } } return headerView } //返回分区头部高度 func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 40 } // UITableViewDataSource协议中的方法,该方法的返回值决定指定分区的尾部 func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { let data = self.allnames[section] return "有\(data.count)个控件" } //创建各单元显示内容(创建参数indexPath指定的单元) func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //为了提供表格显示性能,已创建完成的单元需重复使用 let identify:String = "SwiftCell" //同一形式的单元格重复使用,在声明时已注册 let cell = tableView.dequeueReusableCell(withIdentifier: identify, for: indexPath) cell.accessoryType = .disclosureIndicator let secno = indexPath.section var data = self.allnames[secno] cell.textLabel?.text = data[indexPath.row] return cell } //删除整个分区 func deleteSection(section: Int) { self.adHeaders.remove(at: section) self.allnames.remove(at: section) self.tableView.reloadData() } //设置单元格的编辑的样式 func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { return UITableViewCellEditingStyle.delete } //设置确认删除按钮的文字 func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? { return "删除" } //单元格编辑后(删除或插入)的响应方法 func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { self.allnames[indexPath.section].remove(at: indexPath.row) self.tableView.reloadData() print("你确认了删除按钮") } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
全部评论(3)
你这个 会存在复用问题吧
站长回复:不会吧,我这个也没有复用,能否具体指出哪里有问题。
真机调试也是一样的情况,代码对比过好几次了都是跟你一样的,不知道问题出在哪
站长回复:我检查了下应该是和tableview自带的手势冲突了。代码现已修改,你可以再看下。
为什么第一个分区头可以左滑,其他的分区头都不行
站长回复:你使用真机运行试试,模拟器会有问题。