簡體   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