Files
keyboard/keyBoard/Class/Vender/BMLongPressDragCellCollectionView/BMLongPressDragCellCollectionView.m

730 lines
29 KiB
Mathematica
Raw Normal View History

2025-11-10 20:40:11 +08:00
// MIT License
//
// Copyright (c) 2019 https://liangdahong.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#import "BMLongPressDragCellCollectionView.h"
typedef NS_ENUM(NSUInteger, BMLongPressDragCellCollectionViewScrollDirection) {
BMLongPressDragCellCollectionViewScrollDirectionNone = 0,
BMLongPressDragCellCollectionViewScrollDirectionLeft = 1,
BMLongPressDragCellCollectionViewScrollDirectionRight = 2,
BMLongPressDragCellCollectionViewScrollDirectionUp = 3,
BMLongPressDragCellCollectionViewScrollDirectionDown = 4,
};
@interface BMLongPressDragCellCollectionView ()
///
@property (nonatomic, strong, nullable) UILongPressGestureRecognizer *longGesture;
///
@property (nonatomic, strong, nullable) UIView *snapedView;
///
@property (nonatomic, strong, nullable) CADisplayLink *edgeTimer;
/// IndexPath
@property (nonatomic, strong, nullable) NSIndexPath *oldIndexPath;
///
@property (nonatomic, strong, nullable) NSIndexPath *currentIndexPath;
@property (nonatomic, assign) BOOL isEndDrag; ///<
@property (nonatomic, assign) BOOL banReload; ///<
@property (nonatomic, assign) CGPoint oldPoint; ///<
@property (nonatomic, assign) CGPoint lastPoint; ///<
@end
@implementation BMLongPressDragCellCollectionView
@dynamic delegate, dataSource;
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout {
if (self = [super initWithFrame:frame collectionViewLayout:layout]) {
[self initConfiguration];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self initConfiguration];
}
return self;
}
- (void)dealloc {
[self _stopEdgeTimer];
}
#pragma mark - getters setters
- (void)setCanDrag:(BOOL)canDrag {
_canDrag = canDrag;
self.longGesture.enabled = _canDrag;
}
- (void)setMinimumPressDuration:(NSTimeInterval)minimumPressDuration {
_minimumPressDuration = minimumPressDuration;
self.longGesture.minimumPressDuration = minimumPressDuration;
}
- (void)setDragZoomScale:(CGFloat)dragZoomScale {
if (dragZoomScale < 0.1) {
dragZoomScale = 1.2;
}
_dragZoomScale = dragZoomScale;
}
- (void)setDragSpeed:(CGFloat)dragSpeed {
if (dragSpeed < 0.5) {
dragSpeed = 8.0;
}
_dragSpeed = dragSpeed;
}
- (void)setDragSnapedViewBackgroundColor:(UIColor *)dragSnapedViewBackgroundColor {
_dragSnapedViewBackgroundColor = dragSnapedViewBackgroundColor;
_snapedView.backgroundColor = dragSnapedViewBackgroundColor;
}
- (UILongPressGestureRecognizer *)longGesture {
if (!_longGesture) {
_longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlelongGesture:)];
_longGesture.minimumPressDuration = _minimumPressDuration;
}
return _longGesture;
}
// iOS 10 UICollectionView使bug,
// https://developer.apple.com/documentation/uikit/uicollectionview/1771771-prefetchingenabled
// https://sxgfxm.github.io/blog/2016/10/18/uicollectionview-ios10-new-features
- (void)setPrefetchingEnabled:(BOOL)prefetchingEnabled {
[super setPrefetchingEnabled:NO];
}
#pragma mark -
- (void)initConfiguration {
_canDrag = YES;
_minimumPressDuration = 0.5;
_dragZoomScale = 1.2;
_dragCellAlpha = 1.0;
_dragSpeed = 8.0;
[self addGestureRecognizer:self.longGesture];
// iOS 10 UICollectionView 使bug
// https://developer.apple.com/documentation/uikit/uicollectionview/1771771-prefetchingenabled
// https://sxgfxm.github.io/blog/2016/10/18/uicollectionview-ios10-new-features
if (@available(iOS 10.0, *)) {
self.prefetchingEnabled = NO;
}
}
- (void)reloadData {
if (_banReload) {
return;
}
[super reloadData];
}
- (void)insertSections:(NSIndexSet *)sections {
if (_banReload) {
return;
}
[super insertSections:sections];
}
- (void)deleteSections:(NSIndexSet *)sections {
if (_banReload) {
return;
}
[super deleteSections:sections];
}
- (void)reloadSections:(NSIndexSet *)sections {
if (_banReload) {
return;
}
[super reloadSections:sections];
}
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection {
if (_banReload) {
return;
}
[super moveSection:section toSection:newSection];
}
- (void)insertItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths {
if (_banReload) {
return;
}
[super insertItemsAtIndexPaths:indexPaths];
}
- (void)deleteItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths {
if (_banReload) {
return;
}
[super deleteItemsAtIndexPaths:indexPaths];
}
- (void)reloadItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths {
if (_banReload) {
return;
}
[super reloadItemsAtIndexPaths:indexPaths];
}
- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath {
if (_banReload) {
return;
}
[super moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
}
- (__kindof UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [super dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
//
if (_isEndDrag) {
cell.hidden = NO;
} else {
cell.hidden = (self.oldIndexPath
&& self.oldIndexPath.item == indexPath.item
&& self.oldIndexPath.section == indexPath.section);
}
return cell;
}
- (nullable NSIndexPath *)_getChangedNullIndexPath {
__block NSIndexPath *index = nil;
CGPoint point = [self.longGesture locationInView:self];
NSInteger number = self.numberOfSections;
while (number--) {
NSInteger row = [self.dataSource collectionView:self numberOfItemsInSection:number];
if (row == 0) {
//
CGRect headerFrame = [self layoutAttributesForSupplementaryElementOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:number]].frame;
CGRect footerFrame = [self layoutAttributesForSupplementaryElementOfKind:UICollectionElementKindSectionFooter atIndexPath:[NSIndexPath indexPathForItem:0 inSection:number]].frame;
CGRect frame = CGRectZero;
if (((UICollectionViewFlowLayout *)self.collectionViewLayout).scrollDirection == UICollectionViewScrollDirectionHorizontal) {
//
frame = CGRectMake(CGRectGetMinX(headerFrame),
CGRectGetMinY(headerFrame),
CGRectGetMaxX(footerFrame) - CGRectGetMidX(headerFrame),
CGRectGetWidth(footerFrame));
if (frame.size.width < 10.0) {
// 10.0 10.0
frame.size.width = 10.0;
frame.size.height = CGRectGetHeight(self.frame);
frame.origin.x -= 5.0;
}
} else {
//
frame = CGRectMake(CGRectGetMinX(headerFrame),
CGRectGetMinY(headerFrame),
CGRectGetWidth(footerFrame),
CGRectGetMaxY(footerFrame) - CGRectGetMidY(headerFrame));
if (frame.size.height < 10.0) {
// 10.0 10.0
frame.size.height = 10.0;
frame.size.width = CGRectGetWidth(self.frame);
frame.origin.y -= 5.0;
}
}
if (CGRectContainsPoint(frame, point)) {
//
return [NSIndexPath indexPathForItem:0 inSection:number];
}
}
}
return index;
}
- (nullable NSIndexPath *)_getChangedIndexPath {
__block NSIndexPath *index = nil;
CGPoint point = [self.longGesture locationInView:self];
// Cell Cell
[[self visibleCells] enumerateObjectsUsingBlock:^(__kindof UICollectionViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (CGRectContainsPoint(obj.frame, point)) {
index = [self indexPathForCell:obj];
*stop = YES;
}
}];
// Cell index
if (index) {
if ((index.section == self.oldIndexPath.section) && (index.item == self.oldIndexPath.item)) {
return nil;
}
return index;
}
// Cell
__block CGFloat width = MAXFLOAT;
__weak typeof(self) weakSelf = self;
[[self visibleCells] enumerateObjectsUsingBlock:^(__kindof UICollectionViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (CGRectContainsPoint(obj.frame, point)) {
index = [self indexPathForCell:obj];
*stop = YES;
}
__strong typeof(weakSelf) self = weakSelf;
CGPoint p1 = self.snapedView.center;
CGPoint p2 = obj.center;
//
CGFloat distance = sqrt(pow((p1.x - p2.x), 2) + pow((p1.y - p2.y), 2));
if (distance < width) {
width = distance;
index = [self indexPathForCell:obj];
}
}];
if (!index) {
return nil;
}
if ((index.section == self.oldIndexPath.section) && (index.item == self.oldIndexPath.item)) {
// Cell , return nil
return nil;
}
return index;
}
//
- (BMLongPressDragCellCollectionViewScrollDirection)_setScrollDirection {
if (((self.bounds.size.height + self.contentOffset.y - _snapedView.center.y) < (_snapedView.bounds.size.height / 2))
&& ((self.bounds.size.height + self.contentOffset.y) < self.contentSize.height)) {
return BMLongPressDragCellCollectionViewScrollDirectionDown;
} else if (((_snapedView.center.y - self.contentOffset.y) < (_snapedView.bounds.size.height / 2))
&& self.contentOffset.y > 0) {
return BMLongPressDragCellCollectionViewScrollDirectionUp;
} else if (((self.bounds.size.width + self.contentOffset.x) - (_snapedView.center.x)) < (_snapedView.bounds.size.width / 2)
&& (self.bounds.size.width + self.contentOffset.x) < self.contentSize.width) {
return BMLongPressDragCellCollectionViewScrollDirectionRight;
} else if (((_snapedView.center.x - self.contentOffset.x) < (_snapedView.bounds.size.width) / 2)
&& self.contentOffset.x > 0) {
return BMLongPressDragCellCollectionViewScrollDirectionLeft;
}
return BMLongPressDragCellCollectionViewScrollDirectionNone;
}
// UICollectionView
- (void)_updateSourceData {
//
NSMutableArray *array = [self.dataSource dataSourceWithDragCellCollectionView:self].mutableCopy;
//
BOOL dataTypeCheck = ([self numberOfSections] != 1 || ([self numberOfSections] == 1 && [array[0] isKindOfClass:NSArray.class]));
if (dataTypeCheck) {
for (int i = 0; i < array.count; i ++) {
// NSMutableArray
[array replaceObjectAtIndex:i withObject:[array[i] mutableCopy]];
}
}
if (_currentIndexPath.section == _oldIndexPath.section) {
NSMutableArray *orignalSection = dataTypeCheck ? array[_oldIndexPath.section] : array;
if (_currentIndexPath.item > _oldIndexPath.item) {
for (NSUInteger i = _oldIndexPath.item; i < _currentIndexPath.item ; i ++) {
[orignalSection exchangeObjectAtIndex:i withObjectAtIndex:i + 1];
}
} else {
for (NSUInteger i = _oldIndexPath.item; i > _currentIndexPath.item ; i --) {
[orignalSection exchangeObjectAtIndex:i withObjectAtIndex:i - 1];
}
}
} else {
NSMutableArray *orignalSection = array[_oldIndexPath.section];
NSMutableArray *currentSection = array[_currentIndexPath.section];
[currentSection insertObject:orignalSection[_oldIndexPath.item] atIndex:_currentIndexPath.item];
// https://github.com/liangdahong/BMLongPressDragCellCollectionView/issues/16
// [ , OC ]
// [orignalSection removeObject:orignalSection[_oldIndexPath.item]];
[orignalSection removeObjectAtIndex:_oldIndexPath.item];
}
// ==========
//
// 使使 reloadData
// https://github.com/liangdahong/BMLongPressDragCellCollectionView/issues/14
self.banReload = YES;
[self.delegate dragCellCollectionView:self newDataArrayAfterMove:array];
self.banReload = NO;
}
- (void)_setEdgeTimer{
if (!_edgeTimer) {
_edgeTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(_edgeScroll)];
[_edgeTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
}
- (void)_stopEdgeTimer{
if (_edgeTimer) {
[_edgeTimer invalidate];
_edgeTimer = nil;
}
}
- (void)_edgeScroll {
BMLongPressDragCellCollectionViewScrollDirection scrollDirection = [self _setScrollDirection];
if (BMLongPressDragCellCollectionViewScrollDirectionNone == scrollDirection) {
return;
}
switch (scrollDirection) {
case BMLongPressDragCellCollectionViewScrollDirectionLeft:{
// NO
[self setContentOffset:CGPointMake(self.contentOffset.x - _dragSpeed, self.contentOffset.y) animated:NO];
_snapedView.center = CGPointMake(_snapedView.center.x - _dragSpeed, _snapedView.center.y);
_lastPoint.x -= _dragSpeed;
}
break;
case BMLongPressDragCellCollectionViewScrollDirectionRight:{
[self setContentOffset:CGPointMake(self.contentOffset.x + _dragSpeed, self.contentOffset.y) animated:NO];
_snapedView.center = CGPointMake(_snapedView.center.x + _dragSpeed, _snapedView.center.y);
_lastPoint.x += _dragSpeed;
}
break;
case BMLongPressDragCellCollectionViewScrollDirectionUp:{
[self setContentOffset:CGPointMake(self.contentOffset.x, self.contentOffset.y - _dragSpeed) animated:NO];
_snapedView.center = CGPointMake(_snapedView.center.x, _snapedView.center.y - _dragSpeed);
_lastPoint.y -= _dragSpeed;
}
break;
case BMLongPressDragCellCollectionViewScrollDirectionDown:{
[self setContentOffset:CGPointMake(self.contentOffset.x, self.contentOffset.y + _dragSpeed) animated:NO];
_snapedView.center = CGPointMake(_snapedView.center.x, _snapedView.center.y + _dragSpeed);
_lastPoint.y += _dragSpeed;
}
break;
default:
break;
}
// Cell 沿
//
[UIView animateWithDuration:0.1 animations:^{
self.snapedView.center = self.lastPoint;
}];
// Cell
NSIndexPath *index1 = [self _getChangedNullIndexPath];
NSIndexPath *index = nil;
index = index1 ? : [self _getChangedIndexPath];
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCellCollectionView:changedDragAtPoint:)]) {
[self.delegate dragCellCollectionView:self changedDragAtPoint:_lastPoint];
}
if (!index) {
return;
}
//
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCellCollectionViewShouldBeginExchange:sourceIndexPath:toIndexPath:)]) {
if (![self.delegate dragCellCollectionViewShouldBeginExchange:self sourceIndexPath:_oldIndexPath toIndexPath:index]) {
return;
}
}
_currentIndexPath = index;
UICollectionViewCell *cell1 = [self cellForItemAtIndexPath:_currentIndexPath];
NSIndexPath *sourceIndexPath = _oldIndexPath;
NSIndexPath *toIndexPath = _currentIndexPath;
if (!index1) {
self.oldPoint = cell1.center;
//
[self _updateSourceData];
// cell
[self moveItemAtIndexPath:_oldIndexPath toIndexPath:_currentIndexPath];
// indexPath
_oldIndexPath = _currentIndexPath;
// Cell ,
//
[self reloadItemsAtIndexPaths:@[_oldIndexPath]];
} else {
//
[self _updateSourceData];
// cell
[self moveItemAtIndexPath:_oldIndexPath toIndexPath:_currentIndexPath];
self.oldPoint = [self cellForItemAtIndexPath:_currentIndexPath].center;
// indexPath
_oldIndexPath = _currentIndexPath;
[self reloadItemsAtIndexPaths:@[_oldIndexPath]];
}
//
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCellCollectionViewShouldEndExchange:sourceIndexPath:toIndexPath:)]) {
[self.delegate dragCellCollectionViewShouldEndExchange:self sourceIndexPath:sourceIndexPath toIndexPath:toIndexPath];
}
}
#pragma mark -
- (void)handlelongGesture:(UILongPressGestureRecognizer *)longGesture {
CGPoint point = [longGesture locationInView:self];
NSIndexPath *indexPath = [self indexPathForItemAtPoint:point];
switch (longGesture.state) {
case UIGestureRecognizerStateBegan: {
//
self.userInteractionEnabled = NO;
_oldIndexPath = indexPath;
// Cell , cell break
if (_oldIndexPath == nil) {
self.longGesture.enabled = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (self.canDrag) {
self.longGesture.enabled = YES;
}
});
break;
}
// Cell
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCellCollectionViewShouldBeginMove:indexPath:)]) {
if (![self.delegate dragCellCollectionViewShouldBeginMove:self indexPath:_oldIndexPath]) {
_oldIndexPath = nil;
self.longGesture.enabled = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (self.canDrag) {
self.longGesture.enabled = YES;
}
});
break;
}
}
self.isEndDrag = NO;
// cell
UICollectionViewCell *cell = [self cellForItemAtIndexPath:_oldIndexPath];
self.oldPoint = cell.center;
// nil
if (_snapedView) {
_snapedView = nil;
}
// View
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCellCollectionView: startDragAtIndexPath:)]) {
_snapedView = [self.delegate dragCellCollectionView:self startDragAtIndexPath:indexPath];
}
if (!_snapedView) {
// 使 cell view
_snapedView = [cell snapshotViewAfterScreenUpdates:NO];
}
//
if (_dragSnapedViewBackgroundColor) {
_snapedView.backgroundColor = _dragSnapedViewBackgroundColor;
}
//
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCellCollectionView: dragView:indexPath:)]) {
[self.delegate dragCellCollectionView:self dragView:_snapedView indexPath:indexPath];
}
// frame
_snapedView.frame = cell.frame;
// collectionView
[self addSubview:_snapedView];
// cell
cell.hidden = YES;
//
CGPoint currentPoint = point;
//
[UIView animateWithDuration:0.25 animations:^{
self.snapedView.transform = CGAffineTransformMakeScale(self.dragZoomScale, self.dragZoomScale);
self.snapedView.center = CGPointMake(currentPoint.x, currentPoint.y);
self.snapedView.alpha = self.dragCellAlpha;
}];
}
break;
case UIGestureRecognizerStateChanged: {
// collectionView
// https://github.com/liangdahong/BMLongPressDragCellCollectionView/issues/15
if (!_edgeTimer) {
[self _setEdgeTimer];
}
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCellCollectionView:changedDragAtPoint:)]) {
[self.delegate dragCellCollectionView:self changedDragAtPoint:point];
}
//
_lastPoint = point;
//
[UIView animateWithDuration:0.1 animations:^{
self.snapedView.center = self.lastPoint;
}];
NSIndexPath *index1 = [self _getChangedNullIndexPath];
NSIndexPath *index = nil;
if (index1) {
index = index1;
} else {
index = [self _getChangedIndexPath];
}
// || Cell
if (!index) {
break;
}
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCellCollectionViewShouldBeginExchange:sourceIndexPath:toIndexPath:)]) {
if (![self.delegate dragCellCollectionViewShouldBeginExchange:self sourceIndexPath:_oldIndexPath toIndexPath:index]) {
break;
}
}
_currentIndexPath = index;
UICollectionViewCell *cell1 = [self cellForItemAtIndexPath:_currentIndexPath];
NSIndexPath *sourceIndexPath = _oldIndexPath;
NSIndexPath *toIndexPath = _currentIndexPath;
if (!index1) {
self.oldPoint = cell1.center;
//
[self _updateSourceData];
// cell
[self moveItemAtIndexPath:_oldIndexPath toIndexPath:_currentIndexPath];
// indexPath
_oldIndexPath = _currentIndexPath;
[self reloadItemsAtIndexPaths:@[_oldIndexPath]];
} else {
//
[self _updateSourceData];
// cell
[self moveItemAtIndexPath:_oldIndexPath toIndexPath:_currentIndexPath];
self.oldPoint = [self cellForItemAtIndexPath:_currentIndexPath].center;
// indexPath
_oldIndexPath = _currentIndexPath;
[self reloadItemsAtIndexPaths:@[_oldIndexPath]];
}
//
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCellCollectionViewShouldEndExchange:sourceIndexPath:toIndexPath:)]) {
[self.delegate dragCellCollectionViewShouldEndExchange:self sourceIndexPath:sourceIndexPath toIndexPath:toIndexPath];
}
break;
}
break;
default: {
self.userInteractionEnabled = YES;
if (self.delegate && [self.delegate respondsToSelector:@selector(dragCellCollectionView:endedDragAtPoint:)]) {
[self.delegate dragCellCollectionView:self endedDragAtPoint:point];
}
if (longGesture.isEnabled) {
if (!self.oldIndexPath) {
return;
}
UICollectionViewCell *cell = [self cellForItemAtIndexPath:_oldIndexPath];
//
self.userInteractionEnabled = NO;
//
self.isEndDrag = YES;
// cell
[UIView animateWithDuration:0.25 animations:^{
if (!cell) {
self.snapedView.center = self.oldPoint;
} else {
self.snapedView.center = cell.center;
}
self.snapedView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
self.snapedView.alpha = 1.0;
} completion:^(BOOL finished) {
// cell
[self.snapedView removeFromSuperview];
self.snapedView = nil;
cell.hidden = NO;
self.userInteractionEnabled = YES;
}];
}
//
self.oldIndexPath = nil;
[self _stopEdgeTimer];
}
break;
}
}
- (void)dragMoveItemToIndexPath:(NSIndexPath *)newIndexPath {
if (self.isEndDrag) {
return;
}
self.isEndDrag = YES;
self.longGesture.enabled = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (self.canDrag) {
self.longGesture.enabled = YES;
}
});
if (_oldIndexPath) {
_currentIndexPath = newIndexPath;
//
[self _updateSourceData];
// cell
[self moveItemAtIndexPath:_oldIndexPath toIndexPath:_currentIndexPath];
// indexPath
_oldIndexPath = newIndexPath;
[self reloadItemsAtIndexPaths:@[newIndexPath]];
UICollectionViewCell *cell = [self cellForItemAtIndexPath:_oldIndexPath];
cell.hidden = YES;
//
self.userInteractionEnabled = NO;
//
self.isEndDrag = YES;
// cell
[UIView animateWithDuration:0.25 animations:^{
if (!cell) {
self.snapedView.center = self.oldPoint;
} else {
self.snapedView.center = cell.center;
}
self.snapedView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
self.snapedView.alpha = 1.0;
} completion:^(BOOL finished) {
// cell
[self.snapedView removeFromSuperview];
cell.hidden = NO;
self.userInteractionEnabled = YES;
}];
}
//
_oldIndexPath = nil;
[self _stopEdgeTimer];
}
@end