Reset CollectionviewCell position on tap gesture

540 views Asked by At

I am working with gestures first time here. Please let me know if my approach is wrong or any better solution.

I am trying to delete the collectionView Cell on swiping Left just like UITableview delete function. Deleting works fine. Now what I want is, Once I swipe the cell and tap anywhere on COllectionView it should swipe back to its original position(same like tableview delete row functionality)

I am using/trying this code Updated viewDidLoad and tapped event

override func viewDidLoad() {
super.viewDidLoad()

        let tap = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
        self.view.addGestureRecognizer(tap)
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let Cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! CustomCell
    Cell.backgroundColor = UIColor.white

    let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(delete(sender:)))
    leftSwipe.direction = UISwipeGestureRecognizerDirection.left
    Cell.addGestureRecognizer(leftSwipe)

    let tap = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
    Cell.addGestureRecognizer(tap)

    Cell.deleteButton.addTarget(self, action: #selector(DeleteCell(sender:)), for: .touchUpInside)
}

func tapped(_ recognizer: UITapGestureRecognizer) {
   // self.collectionView.performBatchUpdates({ 
        //self.collectionView.reloadSections(NSIndexSet(index: 0) as IndexSet)
    //}, completion: nil)


    let point = recognizer.location(in: collectionView)
    let indexPath = collectionView.indexPathForItem(at: point)        
    let cell = self.collectionView.cellForItem(at: indexPath!)

    UIView.animate(withDuration: 0.4) {

        cell?.contentView.frame = CGRect(x: 0, y: 0, width: (cell?.contentView.frame.width)!, height: (cell?.contentView.frame.height)!)
    }

}

func delete(sender: UISwipeGestureRecognizer){

    let cell = sender.view as! CustomCell

    UIView.animate(withDuration: 0.4) {
        cell.contentView.frame = CGRect(x: -90, y: 0, width: cell.contentView.frame.width, height: cell.contentView.frame.height)
    }
}

func DeleteCell(sender : AnyObject){

    let cell = sender.superview as! CustomCell
    let i = self.collectionView.indexPath(for: cell)!.item

    let indexpath = self.collectionView.indexPath(for: cell)
    let array : NSMutableArray = []

    self.collectionView.performBatchUpdates({ 

        self.userArray.remove(at: i)

        array.add(indexpath!)

        self.collectionView.deleteItems(at:array as! [IndexPath])

    }, completion: nil)
}


class CustomCell: UICollectionViewCell {
    let deleteButton: UIButton = {
    let deleteBtn = UIButton()
    deleteBtn.setImage(UIImage(named: "red"), for: .normal)
    deleteBtn.contentMode = .scaleAspectFit
    return deleteBtn
    }()
}

So here I am able to set the cell's position back to original by self.collectionView.performBatchUpdates but its not smooth animation. I tried using

UIView.animate(withDuration: 0.4) {            
    cell.contentView.frame = CGRect(x: 0, y: 0, width:     cell.contentView.frame.width, height: cell.contentView.frame.height)
}

but it works only if swiped cell tapped, not any other cell or anywhere else. Any suggestions would be helpful!!

2

There are 2 answers

0
iUser On BEST ANSWER

Finally, got the solution.

Here is the demo project I found - CollectionViewSlideLeft

Hope it will help someone like me. :)

3
Jacolack On

Right now you are accessing your cell from within itself. The reason it only works to tap on the cell you just swiped is because that is the only cell with that specific instance of UITapGestureRecognizer. To fix this, you should add that tap gesture recognizer to your whole view. Try adding this to your viewDidLoad() method:

let tap = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
self.view.addGestureRecognizer(tap)