Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/102.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在Swift 3中向TableView添加向左滑动手势并返回单元格位置_Ios_Uitableview_Swift3_Uigesturerecognizer - Fatal编程技术网

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

Ios 如何在Swift 3中向TableView添加向左滑动手势并返回单元格位置,ios,uitableview,swift3,uigesturerecognizer,Ios,Uitableview,Swift3,Uigesturerecognizer,我有一个TableView,它已经被编码为在使用didSelectRowAt方法选择任何单元格时执行操作 现在,我想在表格(或单元格)中添加一个向左滑动的手势,这样我就可以在滑动单元格而不是轻触单元格时执行辅助操作 1) 我希望单元格在滑动时向左移动,但我不希望在单元格移动的位置添加按钮 2) 相反,我希望能够将单元格向左“拖动”到某个点(比如说中途),然后在该点上使用indexPath执行第二个操作(这样我就知道拖动了哪个单元格) 3) 如果用户停止拖动或放开单元格,我希望它返回到起始位置,并

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

现在,我想在表格(或单元格)中添加一个向左滑动的手势,这样我就可以在滑动单元格而不是轻触单元格时执行辅助操作

1) 我希望单元格在滑动时向左移动,但我不希望在单元格移动的位置添加按钮

2) 相反,我希望能够将单元格向左“拖动”到某个点(比如说中途),然后在该点上使用indexPath执行第二个操作(这样我就知道拖动了哪个单元格)

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

我见过很多这样做的示例,但大多数都在Obj-C中,或者在单元格的同一行中插入按钮

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


编辑:下面是我的完整答案,代码是

我做了一些研究,并创建了一个简单的示例来说明如何实现这一点-创建一个可以滑动和点击的表格单元格。我在音乐播放器中使用它——轻触手机播放歌曲,轻扫同一手机,切换到不同的视图

我基于以下两个现有示例构建了我的解决方案:

我没有可共享的存储库,所以所有代码都在这里

我使用的是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})
    }
    
    }
    
步骤4:

在故事板中连接所有内容

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

  • 在TableView仍处于选中状态的情况下,从Outlets>dataSource拖动到情节提要中的TableView。重复从Outlets>delegate开始

步骤5:

  • 快跑

我不会详细介绍任何代码,因为顶部的两个链接做得很好。这仅仅是关于拥有完整、简单、干净的代码来构建。享受吧。

OP所要求的并不是可能的重复about@MichaelFourre这是正确的。然而,我刚刚发现了两个帖子,显示了我在寻找什么,其中一个几乎就是它。概述:准确:你可以写下你的解决方案,然后当你完成后,用一些实现片段给自己一个答案,以防其他人想看到它,我一弄明白就可以了!有一些小问题,因为示例不在Swift 3中
//
//  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")
}
}