iOS怎么使用UICollectionView实现拖拽移动单元格
发表于:2025-11-09 作者:千家信息网编辑
千家信息网最后更新 2025年11月09日,这篇"iOS怎么使用UICollectionView实现拖拽移动单元格"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有
千家信息网最后更新 2025年11月09日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安全错误
数据库的锁怎样保障安全
网络安全法施行一周年
研究生学 网络安全 天赋
软件开发标兵主要业绩
怎么用exce分析数据库
分布式数据库国外研究情况
数据库入学成绩规则怎么设置
软件开发要考研吗
媒体服务器耗电超级严重怎么解
安徽多功能软件开发价格表
edb数据库无法打开
当贝网络安全要收费吗
数据库cas详解
如何给服务器新增ip
web服务器中的网站日志文件是
sql数据库表格迁移
青少年网络安全教育彩铅画
金融网络安全知识问答
创建数据库备份的命令
电商购物软件开发怎么收费
数据库改过密码
电信网络安全教育问题
access数据库 共享
查看数据库关系图
亳州网络安全演习
腾讯云服务器的密码
计算机网络技术安卓应用
云服务器esc是什么
福州网络安全平台
数据库cas详解
数据库中refid是什么意思