iOS怎么使用UICollectionView实现拖拽移动单元格
发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇"iOS怎么使用UICollectionView实现拖拽移动单元格"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有
千家信息网最后更新 2026年11月03日iOS怎么使用UICollectionView实现拖拽移动单元格
这篇"iOS怎么使用UICollectionView实现拖拽移动单元格"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"iOS怎么使用UICollectionView实现拖拽移动单元格"文章吧。
一.介绍
iOS9提供API实现单元格排序呢功能,使用UICollectionView及其代理方法.iOS9之后有自带方法可以实现该效果,只需添加长按手势,实现手势方法和调用iOS9的API交换数据,iOS9之前需要自己写方法实现这效果,除了要添加长按手势,这里还需要利用截图替换原理,手动计算移动位置来处理视图交换和数据交换.
二.方法和步骤
1.创建工程项目和视图控制器,如下图

2.声明对象和设置代理和数据源代理
@interface ViewController ()@property (nonatomic, strong) NSMutableArray *dataArr;@property (nonatomic, strong) UICollectionView *collectionView;/**之前选中cell的NSIndexPath*/@property (nonatomic, strong) NSIndexPath *oldIndexPath;/**单元格的截图*/@property (nonatomic, strong) UIView *snapshotView;/**之前选中cell的NSIndexPath*/@property (nonatomic, strong) NSIndexPath *moveIndexPath; @end
3.初始化UICollectionView,并添加长按手势,在viewDidLoad中初始化
CGFloat SCREEN_WIDTH = self.view.frame.size.width; UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; flowLayout.itemSize = CGSizeMake((SCREEN_WIDTH-40.0)/3, (SCREEN_WIDTH-40.0)/3); UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 50.0, SCREEN_WIDTH, (SCREEN_WIDTH-40.0)/3+20.0) collectionViewLayout:flowLayout]; collectionView.dataSource = self; collectionView.delegate = self; collectionView.backgroundColor = [UIColor whiteColor]; [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"uicollectionviewcell"]; [self.view addSubview:self.collectionView = collectionView]; // 添加长按手势 UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlelongGesture:)]; [collectionView addGestureRecognizer:longPress];
4.实例化数据源,(50个随机颜色,透明度0.8),在viewDidLoad中初始化
self.dataArr = [[NSMutableArray alloc] init];for (NSInteger index = 0; index < 50; index ++) { CGFloat hue = (arc4random()%256/256.0); //0.0 到 1.0 CGFloat saturation = (arc4random()8/256.0)+0.5; //0.5 到 1.0 CGFloat brightness = (arc4random()8/256.0)+0.5; //0.5 到 1.0 UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:0.5]; [self.dataArr addObject:color]; }5.实现UICollectionView的UICollectionViewDataSource的两个必须实现的方法
#pragma mark - UICollectionViewDataSource- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return self.dataArr.count;} - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"uicollectionviewcell" forIndexPath:indexPath]; cell.backgroundColor = self.dataArr[indexPath.row]; return cell;}6.重点来了,实现长按手势方法
#pragma mark - 长按手势- (void)handlelongGesture:(UILongPressGestureRecognizer *)longPress{ if ([[[UIDevice currentDevice] systemVersion] floatValue] < 9.0) { [self action:longPress]; } else { [self iOS9_Action:longPress]; }}7.iOS9之后的实现
#pragma mark - iOS9 之后的方法- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath{ // 返回YES允许row移动 return YES;} - (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{ //取出移动row数据 id color = self.dataArr[sourceIndexPath.row]; //从数据源中移除该数据 [self.dataArr removeObject:color]; //将数据插入到数据源中的目标位置 [self.dataArr insertObject:color atIndex:destinationIndexPath.row];} - (void)iOS9_Action:(UILongPressGestureRecognizer *)longPress{ switch (longPress.state) { case UIGestureRecognizerStateBegan: { //手势开始 //判断手势落点位置是否在row上 NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:[longPress locationInView:self.collectionView]]; if (indexPath == nil) { break; } UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath]; [self.view bringSubviewToFront:cell]; //iOS9方法 移动cell [self.collectionView beginInteractiveMovementForItemAtIndexPath:indexPath]; } break; case UIGestureRecognizerStateChanged: { // 手势改变 // iOS9方法 移动过程中随时更新cell位置 [self.collectionView updateInteractiveMovementTargetPosition:[longPress locationInView:self.collectionView]]; } break; case UIGestureRecognizerStateEnded: { // 手势结束 // iOS9方法 移动结束后关闭cell移动 [self.collectionView endInteractiveMovement]; } break; default: //手势其他状态 [self.collectionView cancelInteractiveMovement]; break; }}8.iOS9之前的实现
#pragma mark - iOS9 之前的方法- (void)action:(UILongPressGestureRecognizer *)longPress{ switch (longPress.state) { case UIGestureRecognizerStateBegan: { // 手势开始 //判断手势落点位置是否在row上 NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:[longPress locationInView:self.collectionView]]; self.oldIndexPath = indexPath; if (indexPath == nil) { break; } UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath]; // 使用系统的截图功能,得到cell的截图视图 UIView *snapshotView = [cell snapshotViewAfterScreenUpdates:NO]; snapshotView.frame = cell.frame; [self.view addSubview:self.snapshotView = snapshotView]; // 截图后隐藏当前cell cell.hidden = YES; CGPoint currentPoint = [longPress locationInView:self.collectionView]; [UIView animateWithDuration:0.25 animations:^{ snapshotView.transform = CGAffineTransformMakeScale(1.05, 1.05); snapshotView.center = currentPoint; }]; } break; case UIGestureRecognizerStateChanged: { // 手势改变 //当前手指位置 截图视图位置随着手指移动而移动 CGPoint currentPoint = [longPress locationInView:self.collectionView]; self.snapshotView.center = currentPoint; // 计算截图视图和哪个可见cell相交 for (UICollectionViewCell *cell in self.collectionView.visibleCells) { // 当前隐藏的cell就不需要交换了,直接continue if ([self.collectionView indexPathForCell:cell] == self.oldIndexPath) { continue; } // 计算中心距 CGFloat space = sqrtf(pow(self.snapshotView.center.x - cell.center.x, 2) + powf(self.snapshotView.center.y - cell.center.y, 2)); // 如果相交一半就移动 if (space <= self.snapshotView.bounds.size.width / 2) { self.moveIndexPath = [self.collectionView indexPathForCell:cell]; //移动 会调用willMoveToIndexPath方法更新数据源 [self.collectionView moveItemAtIndexPath:self.oldIndexPath toIndexPath:self.moveIndexPath]; //设置移动后的起始indexPath self.oldIndexPath = self.moveIndexPath; break; } } } break; default: { // 手势结束和其他状态 UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:self.oldIndexPath]; // 结束动画过程中停止交互,防止出问题 self.collectionView.userInteractionEnabled = NO; // 给截图视图一个动画移动到隐藏cell的新位置 [UIView animateWithDuration:0.25 animations:^{ self.snapshotView.center = cell.center; self.snapshotView.transform = CGAffineTransformMakeScale(1.0, 1.0); } completion:^(BOOL finished) { // 移除截图视图,显示隐藏的cell并开始交互 [self.snapshotView removeFromSuperview]; cell.hidden = NO; self.collectionView.userInteractionEnabled = YES; }]; } break; }}三.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);
以上就是关于"iOS怎么使用UICollectionView实现拖拽移动单元格"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。
移动
手势
方法
数据
截图
位置
视图
单元
内容
数据源
代理
功能
动画
手指
效果
文章
步骤
状态
知识
篇文章
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网科技公司简介
互联网科技公司的优势
北京互联网科技公司
互联网高科技企业
互联网科技素材视频竖屏
华脉科技工业互联网产品
互联网科技实习生岗位职责
广州恒生互联网科技有限
科技互联网大厂
互联网还是高科技吗
上海宁丞科技互联网
花神(南京)互联网科技有限公司
链环科技传统企业怎么转型互联网
中和天地互联网科技有限公司
长沙互联网科技
张召忠谈中国互联网科技
信承诺互联网科技有限公司
珠海东科互联网科技有限公司
科技信息时代互联网发展
10位科技互联网大佬
云南咖啡
互联网科技保险
互联网为科技
互联网 的科技创新
紫鲸互联网科技
华中科技大学互联网
科技创新互联网企业
哈尔滨秒房互联网科技有限公司
互联网科技革命什么开始
启辰互联网科技