Implementation of collectionViewCell mobile (long press or direct drag)

Recently in the home block is similar to the NetEase news editor: long press enter the editing interface, then the mobile cell can be realized by dragging, the study found that two ways: the first is to directly use the system of UICollectionView API mobile, but can only be used on iOS9. So here is another the way.

Source effect example:

Implementation of collectionViewCell mobile (long press or direct drag)
update sample.Gif

Principle part

  1. Add a long press gesture to UICollectionView
  2. In this gesture through selector access to the current gestures in collectionVIew location to obtain a indexPath, if the indexPath is valid, then you can get the corresponding cell. by the indexPath
  3. Will get to the cell screenshot, and then the hidden cell, makes the following screenshot fingers move synchronously by setting this screenshot of the frame, if the screenshots moved to another location cell, then the two cell exchange position by calling the collectionView method, also need to update the collectionView dataSource.

Implementation part

  1. Add a long press let longGes = UILongPressGestureRecognizer gesture on collectionView (target: self, action: #selector (self.longPressd (_:))) collectionView.addGestureRecognizer (longGes)

2 handle response in selector

  • 2.1 get the position of the current gesture let location = ges.locationInView (self.collectionView)
  • 2.2 get the corresponding position in collectionView in indexPath, notice that the indexPath may be nil (such as the fingers are not in the position of cell at the position of the finger) / / when not in the collectionView range of cell nil let notSureIndexPath = self.collectionView.indexPathForItemAtPoint (location)
  • 2.3 through the current status of the different gestures
Implementation of collectionViewCell mobile (long press or direct drag)
traversal state.Png
  • 2.3.1 case.Began if let indexPath at the beginning of the gesture = notSureIndexPath {/ / access to indexPath is effective, you can rest assured that the use of currentIndexPath / / A. / / b. = indexPath let cell = collectionView.cellForItemAtIndexPath (indexPath) snapedImageView! / / C. = getTheCellSnap (cell) deltaSize = CGSize (width: location.x – cell.frame.origin.x, height: – location.y cell.frame.origin.y / / d.) = snapedImageView.transform = CGAffineTransformMakeScale (1.1, 1.1) = 0 / / F. / / E. cell.alpha collectionView.addSubview (snapedImageView)} A. record The current indexPath to enter.Changed state in the process of moving the fingers of the use of
    B. through the indexPath access to the corresponding cell
    C. cell
    D. to obtain the screenshots and set a screenshot of the initial position of
    E. cell
    F. hidden current will be added to the collectionView screenshot
  • 2.3.2 case.Changed finger while moving
A. if / / snapedImageView = = nil {return} / / b. snapedImageView.frame.origin.x = location.x - deltaSize.width = location.y - snapedImageView.frame.origin.y deltaSize.height / / C. If let newIndexPath let = notSureIndexPath, oldIndexPath = currentIndexPath {if newIndexPath! = oldIndexPath & & newIndexPath.section = oldIndexPath.section / / d. collectionView.moveItemAtIndexPath {// only move in the same group (oldIndexPath, toIndexPath: / newIndexPath) update dataSource / / E. cell = let collectionView.cellForItemAtIndexPath (newIndexPath) cell.A? LPHA = 0 / / F. currentIndexPath newIndexPath}} =

A. if the began state did not get to return directly to
B. settings screenshot screenshot of the position, in order to achieve synchronization and finger mobile
C. if the new access to the indexPath and not the same effective and original
D. cell dataSource
E. mobile update, set up a new cell attribute
F. to update the current indexPath

  • 2.3.3 case.End finger off the screen
If let oldIndexPath = currentIndexPath let cell = collectionView.cellForItemAtIndexPath {/ / A. / / b. UIView.animateWithDuration (oldIndexPath)! (0.25, animations: {[unowned self] in self.snapedImageView.transform = CGAffineTransformIdentity self.snapedImageView.frame = cell.frame completion: {[unowned}, self] (_) in self.snapedImageView.removeFromSuperview (self.snapedImageView) = nil self.currentIndexPath = nil cell.alpha = 1})}

A. gets the current move to complete the cell
B. using animation to remove the screenshot and set the current movement to complete the cell property

To the current location, set the collectionView and delegate method of datasource can achieve the following results

Implementation of collectionViewCell mobile (long press or direct drag)
sample effect.Gif

Please see the detailed source code, if you feel there is help, give a star to encourage you, welcome attention