Search code examples
swift3uicollectionviewuitapgesturerecognizerswipe-gestureperformbatchupdates

Reset CollectionviewCell position on tap gesture


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!!


Solution

  • Finally, got the solution.

    Here is the demo project I found - CollectionViewSlideLeft

    Hope it will help someone like me. :)