前言:
排序思路: 拖拽排序的主要思路是利用在UICollectionView
上添加一个长按的手势(UILongPressGestureRecognizer
)实现的。 通过监听手势拖拽开始,拖拽中,拖拽结束的事件,然后根据不同的状态做相应的操作。
效果图如下:
一、在UICollectionView
上添加一个长按的手势,并在UICollectionView
上面添加一个浮动隐藏的cell,便于拖拽
// 添加长按手势
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressRecognizer:)];
longPress.minimumPressDuration = 0.3;
[self.mainView addGestureRecognizer:longPress];
// 添加浮动视图
self.dragingItem = [[WEYuqingChannelCell alloc] initWithFrame:CGRectMake(0, 0, cellWidth, cellWidth/2.0f)]; self.dragingItem.hidden = true;
[self.mainView addSubview:self.dragingItem];
二、拖拽过程的监听
2.1 通过长按操作找到需要被拖动的cell1
2.2 通过拖动cell1找到找到和它交换位置的cell2
2.3 交换cell1和cell2的位置
2.4 替换数据源,把起始位置的数据模型删除,然后将起始位置的数据模型插入到拖拽位置
// 长按手势处理
- (void)longPressRecognizer:(UILongPressGestureRecognizer *)longPress{
CGPoint point = [longPress locationInView:self.mainView];
switch (longPress.state) {
case UIGestureRecognizerStateBegan:{
[self dragBegin:point];
NSLog(@"拖拽开始");
break;
}
case UIGestureRecognizerStateChanged:{
[self dragChanged:point];
NSLog(@"拖拽中");
break;
}
case UIGestureRecognizerStateEnded: {
[self dragEnd];
NSLog(@"拖拽结束");
[self userSortMontiorCompany];
break;
}
default:{
break;
}
}
}
// 拖拽开始 找到被拖拽的item
- (void)dragBegin:(CGPoint)point{
self.dragingIndexPath = [self getDragingIndexPathWithPoint:point];
if (!self.dragingIndexPath) {return;}
[self.mainView bringSubviewToFront:self.dragingItem];
WEYuqingChannelCell *item = (WEYuqingChannelCell*)[self.mainView cellForItemAtIndexPath:self.dragingIndexPath];
item.isMoving = YES;
// 更新被拖拽的item
self.dragingItem.hidden = NO;
self.dragingItem.frame = item.frame;
self.dragingItem.model = item.model;
[self.dragingItem setTransform:CGAffineTransformMakeScale(1.1, 1.1)];
}
// 正在被拖拽中
- (void)dragChanged:(CGPoint)point{
if (!self.dragingIndexPath) {return;}
self.dragingItem.center = point;
self.targetIndexPath = [self getTargetIndexPathWithPoint:point];
// 交换位置 如果没有找到self.targetIndexPath则不交换位置
if (self.dragingIndexPath && self.targetIndexPath) {
// 更新数据源
[self rearrangeInUseTitles];
//更新item位置
[self.mainView moveItemAtIndexPath:self.dragingIndexPath toIndexPath:self.targetIndexPath];
self.dragingIndexPath = self.targetIndexPath;
}
}
// 拖拽结束
- (void)dragEnd{
if (!self.dragingIndexPath) {return;}
CGRect endFrame = [self.mainView cellForItemAtIndexPath:self.dragingIndexPath].frame;
[self.dragingItem setTransform:CGAffineTransformMakeScale(1.0, 1.0)];
[UIView animateWithDuration:0.3 animations:^{
self.dragingItem.frame = endFrame;
}completion:^(BOOL finished) {
self.dragingItem.hidden = YES;
WEYuqingChannelCell *item = (WEYuqingChannelCell*)[self.mainView cellForItemAtIndexPath:self.dragingIndexPath];
item.isMoving = NO;
}];
}
// 获取被拖动IndexPath的方法
- (NSIndexPath*)getDragingIndexPathWithPoint:(CGPoint)point{
NSIndexPath* dragIndexPath = nil;
//最后剩一个怎不可以排序
if ([self.mainView numberOfItemsInSection:0] == 1) {return dragIndexPath;}
for (NSIndexPath *indexPath in self.mainView.indexPathsForVisibleItems) {
//下半部分不需要排序
if (indexPath.section > 0) {continue;}
// 在上半部分中找出相对应的Item
if (CGRectContainsPoint([self.mainView cellForItemAtIndexPath:indexPath].frame, point)) {
// if (indexPath.row != 0) {
// dragIndexPath = indexPath;
// }
dragIndexPath = indexPath;
break;
}
}
return dragIndexPath;
}
// 获取目标IndexPath的方法
- (NSIndexPath*)getTargetIndexPathWithPoint:(CGPoint)point{
NSIndexPath *targetIndexPath = nil;
for (NSIndexPath *indexPath in self.mainView.indexPathsForVisibleItems) {
// 如果是自己不需要排序
if ([indexPath isEqual:self.dragingIndexPath]) {continue;}
//第二组不需要排序
if (indexPath.section > 0) {continue;}
//在第一组中找出将被替换位置的Item
if (CGRectContainsPoint([self.mainView cellForItemAtIndexPath:indexPath].frame, point)) {
// if (indexPath.row != 0) {
// targetIndexPath = indexPath;
// }
targetIndexPath = indexPath;
}
}
return targetIndexPath;
}
//拖拽排序后需要重新排序数据源
- (void)rearrangeInUseTitles {
WEYuqingChannelModel *model = [self.dataArray objectAtIndex:self.dragingIndexPath.row];
[self.dataArray removeObject:model];
[self.dataArray insertObject:model atIndex:self.targetIndexPath.row];
}
三、UI处理完毕,调用数据排序接口就可以了
#pragma mark - 频道排序
- (void)userSortMontiorCompany {
NSMutableArray *idArr = @[].mutableCopy;
for (WEYuqingChannelModel *model in self.dataArray) {
[idArr addObject:model.ID];
}
NSString *idStr = [idArr componentsJoinedByString:@","];
[WEHttpRequest requestWithConfig:^(WEUrlRequestConfig * _Nonnull request) {
request.methodType = WEHttpMethodPOST;
request.baseUrl = HostUrl;
request.url = @"docinfo/channel/sort";
request.parameters = @{@"cnId":idStr};
request.availableType = WERequestAvailableTypeLoged;
[request setValue:[WELoginManager sharedInstance].accessToken forHeaderField:kAccessToken];
} success:^(NSDictionary * _Nullable responseObject) {
NSLog(@"打印日志。%@",responseObject);
[[NSNotificationCenter defaultCenter] postNotificationName:@"channelStatusChanged" object:nil];
} failed:^(NSError * _Nullable error) {
}];
}