Swift - Drag And Drop TableViewCell with Long Gesture Recognizer

前端 未结 3 949
不思量自难忘°
不思量自难忘° 2021-01-02 19:30

So I have seen a lot of posts about reordering cells that pertain to using \"edit mode\", but none for the problem I have. (Excuse me if I am wrong).

I am building a

相关标签:
3条回答
  • 2021-01-02 19:53

    Dave's answer is great. Here is the swift 4 version of this tutorial:

    WayPointCell is your CustomUITableViewCell and wayPoints is the dataSource array for the UITableView

    First, put this in your viewDidLoad, like Alfi mentionend:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        let longpress = UILongPressGestureRecognizer(target: self, action: #selector(longPressGestureRecognized(gestureRecognizer:)))
        self.tableView.addGestureRecognizer(longpress)
    }
    

    Then implement the method:

    func longPressGestureRecognized(gestureRecognizer: UIGestureRecognizer) {
    
        let longpress = gestureRecognizer as! UILongPressGestureRecognizer
        let state = longpress.state
        let locationInView = longpress.location(in: self.tableView)
        var indexPath = self.tableView.indexPathForRow(at: locationInView)
    
        switch state {
        case .began:
            if indexPath != nil {
                Path.initialIndexPath = indexPath
                let cell = self.tableView.cellForRow(at: indexPath!) as! WayPointCell
                My.cellSnapShot = snapshopOfCell(inputView: cell)
                var center = cell.center
                My.cellSnapShot?.center = center
                My.cellSnapShot?.alpha = 0.0
                self.tableView.addSubview(My.cellSnapShot!)
    
                UIView.animate(withDuration: 0.25, animations: {
                    center.y = locationInView.y
                    My.cellSnapShot?.center = center
                    My.cellSnapShot?.transform = CGAffineTransform(scaleX: 1.05, y: 1.05)
                    My.cellSnapShot?.alpha = 0.98
                    cell.alpha = 0.0
                }, completion: { (finished) -> Void in
                    if finished {
                        cell.isHidden = true
                    }
                })
            }
    
        case .changed:
            var center = My.cellSnapShot?.center
            center?.y = locationInView.y
            My.cellSnapShot?.center = center!
            if ((indexPath != nil) && (indexPath != Path.initialIndexPath)) {
    
                self.wayPoints.swapAt((indexPath?.row)!, (Path.initialIndexPath?.row)!)
                //swap(&self.wayPoints[(indexPath?.row)!], &self.wayPoints[(Path.initialIndexPath?.row)!])
                self.tableView.moveRow(at: Path.initialIndexPath!, to: indexPath!)
                Path.initialIndexPath = indexPath
            }
    
        default:
            let cell = self.tableView.cellForRow(at: Path.initialIndexPath!) as! WayPointCell
            cell.isHidden = false
            cell.alpha = 0.0
            UIView.animate(withDuration: 0.25, animations: {
                My.cellSnapShot?.center = cell.center
                My.cellSnapShot?.transform = .identity
                My.cellSnapShot?.alpha = 0.0
                cell.alpha = 1.0
            }, completion: { (finished) -> Void in
                if finished {
                    Path.initialIndexPath = nil
                    My.cellSnapShot?.removeFromSuperview()
                    My.cellSnapShot = nil
                }
            })
        }
    }
    
    func snapshopOfCell(inputView: UIView) -> UIView {
    
        UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0.0)
        inputView.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        let cellSnapshot : UIView = UIImageView(image: image)
        cellSnapshot.layer.masksToBounds = false
        cellSnapshot.layer.cornerRadius = 0.0
        cellSnapshot.layer.shadowOffset = CGSize(width: -5.0, height: 0.0)
        cellSnapshot.layer.shadowRadius = 5.0
        cellSnapshot.layer.shadowOpacity = 0.4
        return cellSnapshot
    }
    
    struct My {
        static var cellSnapShot: UIView? = nil
    }
    
    struct Path {
        static var initialIndexPath: IndexPath? = nil
    }
    
    0 讨论(0)
  • 2021-01-02 19:59

    Since iOS 11 this can be achieved by implementing the built in UITableView drag and drop delegates.

    You will find a detailed description of how to implement them in this answer to a similar question: https://stackoverflow.com/a/57225766/10060753

    0 讨论(0)
  • 2021-01-02 20:05

    Give this tutorial a shot, you'll likely be up and running within 20 minutes:

    Great Swift Drag & Drop tutorial

    It's easy. I've only been developing for 3 months and I was able to implement this. I also tried several others and this was the one I could understand.

    It's written in Swift and it's practically cut and paste. You add the longPress code to your viewDidLoad and then paste the function into the 'body' of your class. The tutorial will guide you but there's not much more to it.

    Quick explanation of the code: This method uses a switch statement to detect whether the longPress just began, changed, or is in default. Different code runs for each case. It takes a snapshot/picture of your long-pressed cell, hides your cell, and moves the snapshot around. When you finished, it unhides your cell and removes the snapshot from the view.

    Warning: My one word of caution is that although this drag/drop looks great and works close to perfectly, there does seem to be an issue where it crashes upon dragging the cell below the lowest/bottom cell.

    Drag & Drop Crash Problem

    0 讨论(0)
提交回复
热议问题