繁体   English   中英

在Swift 3中滑动时如何向TableView添加向左滑动手势并返回单元格位置

[英]How to add a Swipe Left gesture to a TableView and return the cell location when swiped in Swift 3

我有一个TableView,它已经被编码为使用didSelectRowAt方法选择任何单元格时执行的操作。

现在,我想向表格(或单元格)添加向左滑动手势,以便在滑动单元格而不是轻按时可以执行辅助操作。

1)我希望该单元在滑动时向左移动,但我不想在该单元从其移出的空间中添加按钮。

2)相反,我希望能够“拖动”左侧的单元格直到某个点(例如中途),然后在该点执行indexPath的辅助操作(这样我就知道拖动了哪个单元格)。

3)如果用户停止拖动或放开该单元格,我希望它返回到其初始位置,并且不执行任何操作。

我看过很多示例,它们可以完成各种操作,但是大多数示例都在Obj-C中或在与单元格相同的行中插入按钮。

另外,将手势添加到每个单元格是否更好? 将其添加到表中似乎更聪明...

编辑:请参阅下面的代码我完整的答案

我已经进行了一些研究,并创建了一个简单的例子来说明如何创建一个可滑动和点击的表格单元。 我在音乐播放器中使用它-点按一个单元格并播放歌曲,滑动同一单元格并选择另一个视图。

我已经基于以下两个示例构建了解决方案: https : //www.raywenderlich.com/77974/making-a-gesture-driven-to-do-list-app-like-clear-in-swift-part -1

https://gabrielghe.github.io/swift/2016/03/20/swipable-uitableviewcell

我没有要共享的存储库,因此所有代码都在这里。

我正在使用Xcode 8.2.1和Swift 3

第1步:

  • 创建一个新的单视图Swift项目,然后打开情节提要。
  • 将TableView拖动到现有的ViewController上,然后将其拖动以适合视图。

第2步:

  • 将新的Swift文件添加到项目中,并将其命名为“ TableViewCellSliding.swift”。
  • 将以下代码复制/粘贴到新文件中。

     // // TableViewCellSliding.swift // import UIKit protocol SlidingCellDelegate { // tell the TableView that a swipe happened func hasPerformedSwipe(touch: CGPoint) func hasPerformedTap(touch: CGPoint) } class SlidingTableViewCell: UITableViewCell { var delegate: SlidingCellDelegate? var originalCenter = CGPoint() var isSwipeSuccessful = false var touch = CGPoint() required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) // add a PAN gesture let pRecognizer = UIPanGestureRecognizer(target: self, action: #selector(SlidingTableViewCell.handlePan(_:))) pRecognizer.delegate = self addGestureRecognizer(pRecognizer) // add a TAP gesture // note that adding the PAN gesture to a cell disables the built-in tap responder (didSelectRowAtIndexPath) // so we can add in our own here if we want both swipe and tap actions let tRecognizer = UITapGestureRecognizer(target: self, action: #selector(SlidingTableViewCell.handleTap(_:))) tRecognizer.delegate = self addGestureRecognizer(tRecognizer) } override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer { let translation = panGestureRecognizer.translation(in: superview!) //look for right-swipe if (fabs(translation.x) > fabs(translation.y)) && (translation.x > 0){ // look for left-swipe //if (fabs(translation.x) > fabs(translation.y)) && (translation.x < 0){ //print("gesture 1") touch = panGestureRecognizer.location(in: superview) return true } //not left or right - must be up or down return false }else if gestureRecognizer is UITapGestureRecognizer { touch = gestureRecognizer.location(in: superview) return true } return false } func handleTap(_ recognizer: UITapGestureRecognizer){ // call function to get indexPath since didSelectRowAtIndexPath will be disabled delegate?.hasPerformedTap(touch: touch) } func handlePan(_ recognizer: UIPanGestureRecognizer) { if recognizer.state == .began { originalCenter = center } if recognizer.state == .changed { checkIfSwiped(recongizer: recognizer) } if recognizer.state == .ended { let originalFrame = CGRect(x: 0, y: frame.origin.y, width: bounds.size.width, height: bounds.size.height) if isSwipeSuccessful{ delegate?.hasPerformedSwipe(touch: touch) //after 'short' swipe animate back to origin quickly moveViewBackIntoPlaceSlowly(originalFrame: originalFrame) } else { //after successful swipe animate back to origin slowly moveViewBackIntoPlace(originalFrame: originalFrame) } } } func checkIfSwiped(recongizer: UIPanGestureRecognizer) { let translation = recongizer.translation(in: self) center = CGPoint(x: originalCenter.x + translation.x, y: originalCenter.y) //this allows only swipe-right isSwipeSuccessful = frame.origin.x > frame.size.width / 2.0 //pan is 1/2 width of the cell //this allows only swipe-left //isSwipeSuccessful = frame.origin.x < -frame.size.width / 3.0 //pan is 1/3 width of the cell } func moveViewBackIntoPlace(originalFrame: CGRect) { UIView.animate(withDuration: 0.2, animations: {self.frame = originalFrame}) } func moveViewBackIntoPlaceSlowly(originalFrame: CGRect) { UIView.animate(withDuration: 1.5, animations: {self.frame = originalFrame}) } } 

步骤3:

  • 将以下代码复制/粘贴到现有文件“ ViewController.swift”中

     // // ViewController.swift // import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SlidingCellDelegate { @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. tableView.dataSource = self tableView.delegate = self tableView.register(SlidingTableViewCell.self, forCellReuseIdentifier: "cell") tableView.rowHeight = 50; } func hasPerformedSwipe(touch: CGPoint) { if let indexPath = tableView.indexPathForRow(at: touch) { // Access the image or the cell at this index path print("got a swipe row:\\(indexPath.row)") } } func hasPerformedTap(touch: CGPoint){ if let indexPath = tableView.indexPathForRow(at: touch) { // Access the image or the cell at this index path print("got a tap row:\\(indexPath.row)") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int)-> Int { return 100 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell=tableView.dequeueReusableCell(withIdentifier: "cell",for: indexPath) as! SlidingTableViewCell // Configure cell cell.selectionStyle = .none cell.textLabel?.text = "hello \\(indexPath.row)" cell.delegate = self return cell } func tableView(sender: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { // do stuff with indexPath.row and indexPath.section //never make it here because we added a tap gesture but this will print("selected cell") } } 

第四步:

将其全部连接到情节提要。

  • 打开情节提要板视图,然后选择TableView。 转到“连接检查器”(圆圈的右上角箭头),然后从“新建参考插座”拖动到TableView,然后从弹出菜单中选择“ tableView”。

  • 在仍然选择TableView的情况下,从Outlets> dataSource拖到Storyboard中的TableView。 从“ Outlets”>“代理”开始重复。

步骤5:

  • 运行!

我不会详细介绍任何代码,因为顶部的两个链接都做得很好。 这只是具有可以构建的完整,简单,干净的代码。 请享用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM