簡單寫了一個collectionview的拖拽效果,記錄下.只是簡單的實現(xiàn)了拖拽,其它都沒有加
實現(xiàn)思路:
- 首先給
collectionview添加長按的手勢 - 找到當(dāng)前長按的
cell, 截圖保存為一個view(實際拖拽過程中是拖拽的這個view) ,然后隱藏原先的cell - 拖拽截圖的
view,在拖拽的過程中和collectionview上已有的cell進行對比,交換位置,改變數(shù)據(jù) - 拖拽結(jié)束之后,刪除截圖的
view,顯示最開始的cell
具體代碼
- 創(chuàng)建一個繼承
UICollectionViewFlowLayout的類,你也可以直接寫在viewcontroller中.(名字隨便寫的)
#import <UIKit/UIKit.h>
@protocol DFZFBLayoutDelegate <NSObject>
//去改變數(shù)據(jù)源
- (void)moveDataItem:(NSIndexPath*)fromIndexPath toIndexPath:(NSIndexPath*)toIndexPath;
@end
@interface DFZFBLayout : UICollectionViewFlowLayout
@property (nonatomic, assign) id<DFZFBLayoutDelegate> delegate;
@end
- .m中具體的實現(xiàn)
- 這里只是簡單的添加一個手勢去做的,會慢慢改進.
#import "DFZFBLayout.h"
@interface DFZFBLayout ()<UIGestureRecognizerDelegate>
@property (nonatomic, strong) UILongPressGestureRecognizer *longPress;
@property (nonatomic, strong) NSIndexPath *currentIndexPath; //當(dāng)前的IndexPath
@property (nonatomic, strong) UIView *mappingImageCell; //拖動cell的截圖
@end
@implementation DFZFBLayout
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self) {
[self configureObserver];
}
return self;
}
- (instancetype)init{
self = [super init];
if (self) {
[self configureObserver];
}
return self;
}
- (void)dealloc{
[self removeObserver:self forKeyPath:@"collectionView"];
}
#pragma mark - setup
- (void)configureObserver{
[self addObserver:self forKeyPath:@"collectionView" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)setUpGestureRecognizers{
if (self.collectionView == nil) {
return;
}
_longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleLongPress:)];
_longPress.minimumPressDuration = 0.2f;
_longPress.delegate = self;
[self.collectionView addGestureRecognizer:_longPress];
}
#pragma mark - observer
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:@"collectionView"]) {
[self setUpGestureRecognizers];
}else{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)handleLongPress:(UILongPressGestureRecognizer*)longPress
{
switch (longPress.state) {
case UIGestureRecognizerStateBegan:
{
CGPoint location = [longPress locationInView:self.collectionView];
NSIndexPath* indexPath = [self.collectionView indexPathForItemAtPoint:location];
if (!indexPath) return;
self.currentIndexPath = indexPath;
UICollectionViewCell* targetCell = [self.collectionView cellForItemAtIndexPath:self.currentIndexPath];
//得到當(dāng)前cell的映射(截圖)
UIView* cellView = [targetCell snapshotViewAfterScreenUpdates:YES];
self.mappingImageCell = cellView;
self.mappingImageCell.frame = cellView.frame;
targetCell.hidden = YES;
[self.collectionView addSubview:self.mappingImageCell];
cellView.center = targetCell.center;
}
break;
case UIGestureRecognizerStateChanged:
{
CGPoint point = [longPress locationInView:self.collectionView];
//更新cell的位置
self.mappingImageCell.center = point;
NSIndexPath * indexPath = [self.collectionView indexPathForItemAtPoint:point];
if (indexPath == nil ) return;
if (![indexPath isEqual:self.currentIndexPath])
{
//改變數(shù)據(jù)源
if ([self.delegate respondsToSelector:@selector(moveDataItem:toIndexPath:)]) {
[self.delegate moveDataItem:self.currentIndexPath toIndexPath:indexPath];
}
[self.collectionView moveItemAtIndexPath:self.currentIndexPath toIndexPath:indexPath];
self.currentIndexPath = indexPath;
}
}
break;
case UIGestureRecognizerStateEnded:
{
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:self.currentIndexPath];
[UIView animateWithDuration:0.25 animations:^{
self.mappingImageCell.center = cell.center;
} completion:^(BOOL finished) {
[self.mappingImageCell removeFromSuperview];
cell.hidden = NO;
self.mappingImageCell = nil;
self.currentIndexPath = nil;
}];
}
break;
default:
{
}
break;
}
}
@end
應(yīng)用
- 在viewcontroller中代碼:
DFZFBLayout* layout = [[DFZFBLayout alloc]init];
layout.delegate = self;
//layout.dataSource = self;
layout.minimumInteritemSpacing = 1;
layout.minimumLineSpacing = 1;
layout.sectionInset = UIEdgeInsetsMake(1, 1, 1, 1);
layout.headerReferenceSize = CGSizeMake(SCREEN_WIDTH, 40.f);
// layout.footerReferenceSize = CGSizeMake(SCREEN_WIDTH, 0.f);
// [layout setSectionInset:UIEdgeInsetsMake(0, 0,20,0)];
myCollectionView = [[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:layout];
myCollectionView.delegate = self;
myCollectionView.dataSource = self;
myCollectionView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:myCollectionView];
效果

嗨,我是效果圖哦
iOS9之后 提供了API 記錄下,方便以后使用
// Support for reordering
- (BOOL)beginInteractiveMovementForItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0); // returns NO if reordering was prevented from beginning - otherwise YES
- (void)updateInteractiveMovementTargetPosition:(CGPoint)targetPosition NS_AVAILABLE_IOS(9_0);
- (void)endInteractiveMovement NS_AVAILABLE_IOS(9_0);
- (void)cancelInteractiveMovement NS_AVAILABLE_IOS(9_0);
- (void)handlelongGesture:(UILongPressGestureRecognizer *)longGesture {
//判斷手勢狀態(tài)
switch (longGesture.state) {
case UIGestureRecognizerStateBegan:{
//判斷手勢落點位置是否在路徑上
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:[longGesture locationInView:self.collectionView]];
if (indexPath == nil) {
break;
}
//在路徑上則開始移動該路徑上的cell
[self.collectionView beginInteractiveMovementForItemAtIndexPath:indexPath];
}
break;
case UIGestureRecognizerStateChanged:
//移動過程當(dāng)中隨時更新cell位置
[self.collectionView updateInteractiveMovementTargetPosition:[longGesture locationInView:self.collectionView]];
break;
case UIGestureRecognizerStateEnded:
//移動結(jié)束后關(guān)閉cell移動
[self.collectionView endInteractiveMovement];
break;
default:
[self.collectionView cancelInteractiveMovement];
break;
}
}
- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath{
//返回YES允許其item移動
return YES;
}
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath {
//取出源item數(shù)據(jù)
id objc = [_dataSource objectAtIndex:sourceIndexPath.item];
//從資源數(shù)組中移除該數(shù)據(jù)
[_dataSource removeObject:objc];
//將數(shù)據(jù)插入到資源數(shù)組中的目標(biāo)位置上
[_dataSource insertObject:objc atIndex:destinationIndexPath.item];
}