Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to drag a static cell into tableView swift?

I have one tableView in my storyBoard where I added 4 static cell into it and my storyBoard look like:

enter image description here

I don't have any dataSource for this tableView because my cells are static.

And I use below code to drag a cell and it is working fine till I scroll a table.

import UIKit

class TableViewController: UITableViewController {

    var sourceIndexPath: NSIndexPath = NSIndexPath()
    var snapshot: UIView = UIView()
    let longPress: UILongPressGestureRecognizer = {
        let recognizer = UILongPressGestureRecognizer()
        return recognizer
        }()

    override func viewDidLoad() {
        super.viewDidLoad()

        longPress.addTarget(self, action: "longPressGestureRecognized:")
        self.tableView.addGestureRecognizer(longPress)

        self.tableView.allowsSelection = false
    }

    override func viewWillAppear(animated: Bool) {

        self.tableView.reloadData()
    }

    // MARK: UIGestureRecognizer
    func longPressGestureRecognized(gesture: UILongPressGestureRecognizer){

        let state: UIGestureRecognizerState = gesture.state
        let location:CGPoint = gesture.locationInView(self.tableView)
        if let indexPath: NSIndexPath = self.tableView.indexPathForRowAtPoint(location){

            switch(state){

            case UIGestureRecognizerState.Began:
                sourceIndexPath = indexPath

                let cell: UITableViewCell = self.tableView .cellForRowAtIndexPath(indexPath)!

                //take a snapshot of the selected row using helper method
                snapshot = customSnapshotFromView(cell)

                //add snapshot as subview, centered at cell's center
                var center: CGPoint = cell.center
                snapshot.center = center
                snapshot.alpha  = 0.0
                self.tableView.addSubview(snapshot)
                UIView.animateWithDuration(0.25, animations: { () -> Void in
                    center.y = location.y
                    self.snapshot.center = center
                    self.snapshot.transform = CGAffineTransformMakeScale(1.05, 1.05)
                    self.snapshot.alpha = 0.98
                    cell.alpha = 0.0
                    }, completion: { (finished) in
                        cell.hidden = true
                })

            case UIGestureRecognizerState.Changed:
                let cell: UITableViewCell = self.tableView.cellForRowAtIndexPath(indexPath)!

                var center: CGPoint = snapshot.center
                center.y = location.y
                snapshot.center = center
                print("location \(location.y)")

                //is destination valid and is it different form source?
                if indexPath != sourceIndexPath{
                    //update data source
                    //I have commented this part because I am not using any dataSource.
//                    self.customArray.exchangeObjectAtIndex(indexPath.row, withObjectAtIndex: sourceIndexPath.row)
                    //move the row
                    self.tableView.moveRowAtIndexPath(sourceIndexPath, toIndexPath: indexPath)
                    //and update source so it is in sync with UI changes
                    sourceIndexPath = indexPath
                }

                if (location.y < 68) || (location.y > 450) {
                    print("cancelled")
                    self.snapshot.alpha = 0.0
                    cell.hidden = false
                    UIView.animateWithDuration(0.10, animations: { () -> Void in

                        self.snapshot.center = cell.center
                        self.snapshot.transform = CGAffineTransformIdentity
                        self.snapshot.alpha = 0.0
                        //undo fade out
                        cell.alpha = 1.0

                        }, completion: { (finished) in
                            self.snapshot.removeFromSuperview()
                    })
                }

            case UIGestureRecognizerState.Ended:
                //clean up
                print("ended")
                let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
                cell.hidden = false

                UIView.animateWithDuration(0.25, animations: { () -> Void in

                    self.snapshot.center = cell.center
                    self.snapshot.transform = CGAffineTransformIdentity
                    self.snapshot.alpha = 0.0
                    //undo fade out
                    cell.alpha = 1.0

                    }, completion: { (finished) in
                        self.snapshot.removeFromSuperview()
                })
                break

            default:
                break
            }
        }else{
            gesture.cancelsTouchesInView = true
        }
    }

    func customSnapshotFromView(inputView: UIView) -> UIView {

        // Make an image from the input view.
        UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0)
        inputView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext();

        // Create an image view.
        let snapshot = UIImageView(image: image)
        snapshot.layer.masksToBounds = false
        snapshot.layer.cornerRadius = 0.0
        snapshot.layer.shadowOffset = CGSize(width: -5.0, height: 0.0)
        snapshot.layer.shadowRadius = 5.0
        snapshot.layer.shadowOpacity = 0.4

        return snapshot
    }

}

When I scroll after dragging it looks like:

enter image description here

As you can see cell is not appearing again. I want to drag and drop static cell and I want to save it's position so I will not rearrange again when I scroll.

Sample project for more Info.

This is just a demo project But I have added many elements into my cell and every cell have different UI.

like image 732
Dharmesh Kheni Avatar asked Oct 31 '15 18:10

Dharmesh Kheni


2 Answers

There is a library that does exactly what you are looking to do with a very similar approach. It's called FMMoveTableView but it's for cells with a datasource.

I think that what is causing your problem is that when you move the cells around and then you scroll the datasource from the storyboard is no longer in sync with the table and therefore your cell object can't be redrawn.

I think you should implement your table this way:

  1. Make your 4 cells custom cells.
  2. Subclass each one.
  3. Create an Array with numbers 1 to 4
  4. Reorder the array on long drag
  5. Override cellForRowAtIndexPath to show the right cell for the right number
like image 50
Mika Avatar answered Oct 13 '22 11:10

Mika


You can drag uitableview cell from uitableview delegates ....... 1) set the table view editing style to none in its delegate.

2) implement table view delegate to enable dragging of cell i.e canMoveRowAtIndexPath methods...

like image 32
Abhishek Avatar answered Oct 13 '22 10:10

Abhishek