当前位置: 首页 > 编程日记 > 正文

史上第二走心的 iOS11-Drag Drop 教程

原文链接:www.jianshu.com
只需完成个人实名注册,即可获得腾讯云免费套餐!云服务器CVM、云数据库 MYSQL、文件存储 CFS.....应有尽有!https://cloud.tencent.com/act/free

话不多说,先上效果图

普通view拖拽效果
普通view拖拽效果 TableView拖拽效果
TableView拖拽效果CollectionView效果
CollectionView效果muti-touch效果
muti-touch效果多app交互
多app交互

世界上最大的男性交友网站有demo

一.Tips:你必须要知道的概念

1. Drag 和 Drop 是什么呢?
  • 一种以图形展现的方式把数据从一个 app 移动或拷贝到另一个 app(仅限iPad),或者在程序内部进行
  • 充分利用了 iOS11 中新的文件系统,只有在请求数据的时候才会去移动数据,而且保证只传输需要的数据
  • 通过异步的方式进行传输,这样就不会阻塞runloop,从而保证在传输数据的时候用户也有一个顺畅的交互体验
drag和drop的基本交互图和支持的控件
drag和drop的基本交互图和支持的控件
2. 安全性:
  • 拖拽复制的过程不像剪切板那样,而是保证数据只对目标app可见
  • 提供数据源的app可以限制本身的数据源只可在本 app 或者 公司组app 之间有权限使用,当然也可以开放于所有 app,也支持企业用户的管理配置
3. dragSession 的过程
  • Lift:用户长按 item,item 脱离屏幕
  • Drag :用户开始拖拽,此时可进行 自定义视图预览、添加其他item添加内容、悬停进行导航(即iPad 中打开别的app)
  • Set Down :此时用户无非想进行两种操作:取消拖拽 或者 在当前手指离开的位置对 item 进行 drop 操作
  • Data Transfer :目标app 会向 源app 进行数据请求
  • 这些都是围绕交互这一概念构造的:即类似手势识别器的概念,接收到用户的操作后,进行view层级的改变

4. Others
  • 需要给用户提供 muti-touch 的使用,这一点也是为了支持企业用户的管理配置(比如一个手指选中一段文字,长按其处于lifting状态,另外一个手指选中若干张图片,然后打开邮件,把文字和图片放进邮件,视觉反馈是及时的,动画效果也很棒)
iPad 可实现的功能还是很丰富的
iPad 可实现的功能还是很丰富的

二、以CollectionView 为例,讲一下整个拖拽的api使用情况

在API设计方面,分为两个步骤:Drag 和 Drop,对应着两套协议 UICollectionViewDragDelegate 和
UICollectionViewDropDelegate,因此在创建 CollectionView 的时候要增加以下代码:

- (void)buildCollectionView {_collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowLayout];[_collectionView registerClass:[WPFImageCollectionViewCell class] forCellWithReuseIdentifier:imageCellIdentifier];_collectionView.delegate = self;_collectionView.dataSource = self;// 设置代理对象_collectionView.dragDelegate = self;_collectionView.dropDelegate = self;_collectionView.dragInteractionEnabled = YES;_collectionView.reorderingCadence = UICollectionViewReorderingCadenceImmediate;_collectionView.springLoaded = YES;_collectionView.backgroundColor = [UIColor whiteColor];
}
1. 创建CollectionView注意点总结:
  • dragInteractionEnabled 属性在 iPad 上默认是YES,在 iPhone 默认是 NO,只有设置为 YES 才可以进行 drag 操作

  • reorderingCadence (重排序节奏)可以调节集合视图重排序的响应性。 是 CollectionView 独有的属性(相对于UITableView),因为 其独有的二维网格的布局,因此在重新排序的过程中有时候会发生元素回流了,有时候只是移动到别的位置,不想要这样的效果,就可以修改这个属性改变其相应性

    • UICollectionViewReorderingCadenceImmediate:默认值,当开始移动的时候就立即回流集合视图布局,可以理解为实时的重新排序
    • UICollectionViewReorderingCadenceFast:如果你快速移动,CollectionView 不会立即重新布局,只有在停止移动的时候才会重新布局
    • UICollectionViewReorderingCadenceSlow:停止移动再过一会儿才会开始回流,重新布局
  • springLoaded :弹簧加载是一种导航和激活控件的方式,在整个系统中,当处于 dragSession 的时候,只要悬浮在cell上面,就会高亮,然后就会激活

    • UITableView 和 UICollectionView 都可以使用该方式加载,因为他们都遵守 UISpringLoadedInteractionSupporting 协议
    • 当用户在单元格使用弹性加载时,我们要选择 CollectionView 或tableView 中的 item 或cell
    • 使用 - (BOOL)collectionView:shouldSpringLoadItemAtIndexPath:withContext:来自定义也是可以的
  • collectionView:itemsForAddingToDragSession: atIndexPath: :该方法是muti-touch对应的方法

    • 当接收到添加item响应时,会调用该方法向已经存在的drag会话中添加item
    • 如果需要,可以使用提供的点(在集合视图的坐标空间中)进行其他命中测试。
    • 如果该方法未实现,或返回空数组,则不会将任何 item 添加到拖动,手势也会正常的响应
- (NSArray<UIDragItem *> *)collectionView:(UICollectionView *)collectionView itemsForAddingToDragSession:(id<UIDragSession>)session atIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point {NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithObject:self.dataSource[indexPath.item]];UIDragItem *item = [[UIDragItem alloc] initWithItemProvider:itemProvider];return @[item];
}
再放一遍这个效果图
再放一遍这个效果图
2. UICollectionViewDragDelegate(初始化和自定义拖动方法)
  • collectionView: itemsForBeginningDragSession:atIndexPath:提供一个 给定 indexPath 的可进行 drag 操作的 item(类似 hitTest: 方法周到该响应的view )如果返回 nil,则不会发生任何拖拽事件

由于是返回一个数组,因此可以根据自己的需求来实现该方法:比如拖拽一个item,就可以把该组的所有 item 放进 dragSession 中,右上角会有小蓝圈圈显示个数(但是这种情况下要对数组进行重新排序,因为数组中的最后一个元素会成为Lift 操作中的最上面的一个元素,排序后可以让最先进入dragSession的item放在lift效果的最前面)

- (NSArray<UIDragItem *> *)collectionView:(UICollectionView *)collectionView itemsForBeginningDragSession:(id<UIDragSession>)session atIndexPath:(NSIndexPath *)indexPath {NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithObject:self.dataSource[indexPath.item]];UIDragItem *item = [[UIDragItem alloc] initWithItemProvider:itemProvider];self.dragIndexPath = indexPath;return @[item];
}

  • collectionView:dragPreviewParametersForItemAtIndexPath:允许对从取消或返回到 CollectionView 的 item 使用自定义预览,如果该方法没有实现或者返回nil,那么整个 cell 将用于预览
    • UIDragPreviewParameters 有两个属性:
      • backgroundColor 设置背景颜色,因为有的视图本身就是半透明的,添加背景色视觉效果更好
      • visiblePath设置视图的可见区域,比如可以自定义为圆角矩形或图中的某一块区域等,但是要注意裁剪的Rect 在目标视图中必须要有意义;该属性也要标记一下center方便进行定位
裁剪图中的某一块区域
裁剪图中的某一块区域选取的区域也可以大于这张图,实现添加相框的效果
选取的区域也可以大于这张图,实现添加相框的效果 再高级的功能可以实现目标区域内添加多个rect到dragSession
再高级的功能可以实现目标区域内添加多个rect到dragSession
- (nullable UIDragPreviewParameters *)collectionView:(UICollectionView *)collectionView dragPreviewParametersForItemAtIndexPath:(NSIndexPath *)indexPath {// 可以在该方法内使用 贝塞尔曲线 对单元格的一个具体区域进行裁剪UIDragPreviewParameters *parameters = [[UIDragPreviewParameters alloc] init];CGFloat previewLength = self.flowLayout.itemSize.width;CGRect rect = CGRectMake(0, 0, previewLength, previewLength);parameters.visiblePath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:5];parameters.backgroundColor = [UIColor clearColor];return parameters;
}
  • 还有一些对于 drag 生命周期对应的回调方法,可以在这些方法里添加各种动画效果
/* 当 lift animation 完成之后开始拖拽之前会调用该方法* 该方法肯定会对应着 -collectionView:dragSessionDidEnd: 的调用*/
- (void)collectionView:(UICollectionView *)collectionView dragSessionWillBegin:(id<UIDragSession>)session {NSLog(@"dragSessionWillBegin --> drag 会话将要开始");
}// 拖拽结束的时候会调用该方法
- (void)collectionView:(UICollectionView *)collectionView dragSessionDidEnd:(id<UIDragSession>)session {NSLog(@"dragSessionDidEnd --> drag 会话已经结束");
}

当然也可以在这些方法里面设置自定义的dragPreview,比如 iPad 中原生的通讯图、地图所展现的功能

在 dragSessionWillBegin 方法里面自定义 preview 视图
在 dragSessionWillBegin 方法里面自定义 preview 视图
3. UICollectionViewDropDelegate(迁移数据和自定义释放动画)
Drop手势的流程图
Drop手势的流程图
  • collectionView:performDropWithCoordinator: 方法使用 dropCoordinator 去置顶如果处理当前 drop 会话的item 到指定的最终位置, 同时也会根据drop item返回的数据更新数据源
    • 当用户开始进行 drop 操作的时候会调用这个方法
    • 如果该方法不做任何事,将会执行默认的动画
    • 注意:只有在这个方法中才可以请求到数据
    • 请求的方式是异步的,因此不要阻止数据的传输,如果阻止时间过长,就不清楚数据要多久才能到达,系统甚至可能会kill掉你的应用
- (void)collectionView:(UICollectionView *)collectionView performDropWithCoordinator:(id<UICollectionViewDropCoordinator>)coordinator {NSIndexPath *destinationIndexPath = coordinator.destinationIndexPath;UIDragItem *dragItem = coordinator.items.firstObject.dragItem;UIImage *image = self.dataSource[self.dragIndexPath.row];// 如果开始拖拽的 indexPath 和 要释放的目标 indexPath 一致,就不做处理if (self.dragIndexPath.section == destinationIndexPath.section && self.dragIndexPath.row == destinationIndexPath.row) {return;}// 更新 CollectionView[collectionView performBatchUpdates:^{// 目标 cell 换位置[self.dataSource removeObjectAtIndex:self.dragIndexPath.item];[self.dataSource insertObject:image atIndex:destinationIndexPath.item];[collectionView moveItemAtIndexPath:self.dragIndexPath toIndexPath:destinationIndexPath];} completion:^(BOOL finished) {}];[coordinator dropItem:dragItem toItemAtIndexPath:destinationIndexPath];
}
  • collectionView: dropSessionDidUpdate: withDestinationIndexPath: 该方法是提供释放方案的方法,虽然是optional,但是最好实现
    • 当 跟踪 drop 行为在 tableView 空间坐标区域内部时会频繁调用(因此要尽量减少这个方法的工作量,否则帧率就会降低)
    • 当drop手势在某个section末端的时候,传递的目标索引路径还不存在(此时 indexPath 等于 该 section 的行数),这时候会追加到该section 的末尾
    • 在某些情况下,目标索引路径可能为空(比如拖到一个没有cell的空白区域)
    • 请注意,在某些情况下,你的建议可能不被系统所允许,此时系统将执行不同的建议
    • 你可以通过 -[session locationInView:] 做你自己的命中测试
    • UICollectionViewDropIntent对应的三个枚举值
      • UICollectionViewDropIntentUnspecified 将会接收drop,但是具体的位置要稍后才能确定;不会开启一个缺口,可以通过添加视觉效果给用户传达这一信息
      • UICollectionViewDropIntentInsertAtDestinationIndexPathdrop将会被插入到目标索引中;将会打开一个缺口,模拟最后释放后的布局
      • UICollectionViewDropIntentInsertIntoDestinationIndexPathdrop 将会释放在目标索引路径,比如该cell是一个容器(集合),此时不会像

相关文章:

指针的各式定义

1&#xff0c;一个整形数&#xff1a; int a; 2&#xff0c;一个指向整形数的指针&#xff1a; int *a; 3&#xff0c;一个指向指针的指针&#xff0c;它指向的指针指向一个整形数&#xff1a; int **a; 4&#xff0c;一个有10个整形数的数组&#xff1a; int a[10]; 5&#…

AS 400 常用命令

转自&#xff1a;http://blog.chinaunix.net/uid-22375044-id-3049793.html 一、命令技巧 命令构成&#xff1a; CRT* (Creat) 创建 WRK* (Work With) 操作 RMV* (Remove) 去除 DSP* (Display) 显示 ADD* (Add) 添加 CHG* (Change) 改变 DLT* (Delete) 删除 CFG* (Config) 配置…

Hadoop集群搭建(五:Hadoop HA集群模式的安装)

实验 目的 要求 目的&#xff1a; 1、Hadoop的高可用完全分布模式的安装和验证 要求&#xff1a; 完成Hadoop的高可用完全分布模式的安装&#xff1b;Hadoop的相关服务进程能够正常的启动&#xff1b;HDFS能够正常的使用&#xff1b;MapReduce示例程序能够正常运行&#xff1b…

iOS开发业界毒瘤 Hook

原文地址 为什么有这篇博文 不知道何时开始iOS面试开始流行起来询问什么是 Runtime&#xff0c;于是 iOSer 一听 Runtime 总是就提起 MethodSwizzling&#xff0c;开口闭口就是黑科技。但其实如果读者留意过C语言的 Hook 原理其实会发现所谓的钩子都是框架或者语言的设计者预留…

常用rsync命令操作梳理

作为一个运维工程师&#xff0c;经常可能会面对几十台、几百台甚至上千台服务器&#xff0c;除了批量操作外&#xff0c;环境同步、数据同步也是必不可少的技能。说到“同步”&#xff0c;不得不提的利器就是rsync。rsync不但可以在本机进行文件同步&#xff0c;也可以作为远程…

Word英文字符间距太大 中英文输入切换都不行

在Word中输入文字时会遇到这样的情况&#xff0c;就是说中文字符的间距是正常的&#xff0c;但是英文字符间的间距却不正常&#xff0c;总是太宽了&#xff0c;如图&#xff1a; 。 而且这时切换中英文输入都没用&#xff0c;Word的字体设置也正常。后来上网查了下&#xff0c;…

Hadoop集群搭建(六:HBase的安装配置)

实验 目的 要求 目的&#xff1a; 1、HBase的高可用完全分布模式的安装和验证 要求&#xff1a; 完成HBase的高可用完全分布模式的安装&#xff1b;HBase的相关服务进程能够正常的启动&#xff1b;HBase控制台能够正常使用&#xff1b;表创建、数据查询等数据库操作能够正常…

架构师的第一阶段:准备做(Pre-Architecture)

上节说到&#xff0c;做任何事情都可以分为三个阶段&#xff1a;准备做、做、做好。本文&#xff0c;就将进入第一个阶段&#xff0c;准备做阶段。 Pre-Architecture&#xff1a;准备架构 准备架构阶段&#xff0c;最最重要的是弄清楚要做什么东西&#xff0c;即掌握用户需求。…

iOS动画系列之八:使用CAShapeLayer绘画动态流量图

这篇文章通过使用CAShapeLayer和UIBezierPath来画出一个动态显示剩余流量的小动画。 最终实现的效果如下&#xff1a; Paste_Image.png 动态效果图&#xff1a; shapeLayerAni.gif 1. CAShapeLayer 实际中&#xff0c;能够用CALayer完成的任务是比较少的&#xff0c;如果使用这…

hiho_1139_二分+bfs搜索

题目 给定N个点和M条边&#xff0c;从点1出发&#xff0c;到达点T。寻找路径上边的个数小于等于K的路径&#xff0c;求出所有满足条件的路径中最长边长度的最小值。 题目链接:二分 最小化最大值&#xff0c;考虑采用二分搜索。对所有的边长进行排序&#xff0c;二分&#x…

Hadoop集群搭建(七:MySQL的安装配置)

实验 目的 要求 目的&#xff1a; 1、掌握MySQL在集群平台中的安装 要求&#xff1a; 完成MySQL的集群版的安装&#xff1b;MySQL集群的相关服务进程能够正常启动&#xff1b;MySQL集群的SQL服务能够作为系统服务开机自动启动&#xff1b;MySQL客户端能够远程连接MySQL集群的…

如何在VMware虚拟机上安装Linux操作系统(Ubuntu)

作为初学者想变为计算机大牛非一朝一夕&#xff0c;但掌握基本的计算机操作和常识却也不是多么难的事情。所以作为一名工科男&#xff0c;为了把握住接近女神的机会&#xff0c;也为了避免当白痴&#xff0c;学会装系统吧&#xff01;of course为避免把自己的电脑作为牺牲品&am…

cf #363 b

B. One Bombtime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputYou are given a description of a depot. It is a rectangular checkered field of n  m size. Each cell in a field can be empty (".") or…

swift-video-generator:图片加音频生成视频及多视频合并库及演示

阅读 80收藏 92017-11-07原文链接&#xff1a;github.com腾讯云学生优惠套餐&#xff0c;985高校学习云计算的主力机型&#xff0c;2G2核&#xff0c;1M带宽系统盘&#xff08;Linux 50G/Windows 50G&#xff09;免费赠送50GB对象存储空间还有.cn域名一年使用权&#xff01;不要…

Hadoop集群搭建(八:Hive的安装配置)

实验 目的 要求 目的&#xff1a; &#xff08;1&#xff09;掌握数据仓库工具Hive的安装和配置&#xff1b; 要求&#xff1a; 完成Hive工具的安装和配置&#xff1b;Hive工具能够正常启动运行&#xff1b;Hive控制台命令能够正常使用&#xff1b;能够正常操作数据库、表、…

iOS 富文本编辑工厂, 让书写更简便.

由于最近常用富文本, 在编辑一个富文本时需要操作很多的属性, 书写起来很不方便. 所以我将这些相关属性整理并使用链式方式将它简化了一下. 效果请看下面Demo. 项目工程 实现很简单, 我嘴太笨, 这里就不介绍了, 如有兴趣直接看源码吧. 同时可以通过cocoapods来使用它. pod SJAt…

ORACLE 数据的逻辑组成

数据块&#xff08;block&#xff09;Oracle数据块&#xff08;Data Block&#xff09;是一组连续的操作系统块。分配数据库块大小是在Oracle数据库创建时设置的&#xff0c;数据块是Oracle读写的基本单位。数据块的大小一般是操作系统块大小的整数倍&#xff0c;这样可以避免不…

Java 的zip压缩和解压缩

Java 的zip压缩和解压缩好久没有来这写东西了&#xff0c;今天中秋节&#xff0c;有个东西想拿出来分享&#xff0c;一来是工作中遇到的问题&#xff0c;一来是和csdn问候一下&#xff0c;下面就分享一个Java中的zip压缩技术&#xff0c;代码实现比较简单,代码如下&#xff1a;…

Hadoop集群搭建(九:各服务的启动)

1、查看Zookeeper服务状态&#xff0c;若集群中只有一个"leader"节点&#xff0c; 其余的均为"follower"节点&#xff0c;则集群的工作状态正常 $zkServer.sh status 2、在集群中所有主机上使用此命令&#xff0c;启动Zookeeper服务 $zkServer.sh start…

iOS 后台下载及管理库

说起下载第一个想起的就是ASI。一年前接手的新项目是核心功能是视频相关业务&#xff0c;在修改和解决视频下载相关的问题的时候让我体会到了ASI的下载的强大。后来新需求需要视频后台下载&#xff0c;使用NSURLSession的时候&#xff0c;更加深刻的体会到了ASI的强大好用。后来…

(转) 使用Speech SDK 5.1文字转音频

下载地址&#xff1a; http://www.microsoft.com/en-us/download/details.aspx?id10121 SeppchSDK51.exe 语音合成引擎 SpeechSDK51LangPack.exe 支持日语和简体中文需要这个支持。 SpeechSDK51MSM.exe 如果要将引擎作为产品的一部分发布需要这个。 Sp5TTintXP.exe XP下Mike和…

IE8下面的line-height的bug

当line-height小于正常值时&#xff0c;超出的部分将被剪裁掉转载于:https://www.cnblogs.com/jsingleegg/p/js_ie8.html

Hadoop集群的基本操作(一:HDFS操作及MapReduce程序练习)

实验 目的 要求 目的&#xff1a; 理解HDFS在Hadoop体系结构中的角色&#xff1b;熟练使用HDFS操作常用的Shell命令&#xff1b;了解Hadoop集群MapReduce程序的简单使用&#xff1b;&#xff08;上传WordCount的jar执行程序&#xff1b;使用WordCount进行MapReduce计算&#x…

iOS实现动态区域裁剪图片

阅读 249收藏 322017-11-29原文链接&#xff1a;github.com想自己动手搭建一个 Discuz 论坛&#xff1f;试试腾讯云上实验室吧https://cloud.tencent.com/developer/labs 裁剪图片功能在很多上传图片的场景里都需要用到&#xff0c;一方面应用服务器可能对图片的尺寸大小有限制…

每天CookBook之JavaScript-062

鼠标进入事件鼠标离开事件<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>062</title> </head> <body> <div><img src"001" alt"001"><img src…

spring + Quartz定时任务配置

<bean id"exportBatchFileTask" class"com.ydcn.pts.task.ExportBatchFileTask"></bean><bean id"readBatchFileTask" class"com.ydcn.pts.task.ReadBatchFileResultTask"></bean><!-- 生成开卡档&#xf…

Hadoop集群的基本操作(二:HBase的基本操作)

实验 目的 要求 目的&#xff1a; 1、HBase的基本应用 要求&#xff1a; 完成HBase的高可用完全分布模式的安装&#xff1b;HBase的相关服务进程能够正常的启动&#xff1b;HBase控制台能够正常使用&#xff1b;表创建、数据查询等数据库操作能够正常进行&#xff1b; …

Abaqus用户子程序umat的学习

Abaqus用户子程序umat的学习 说明&#xff1a;在文件中&#xff0c;&#xff01;后面的内容为注释内容。本文为学习心得&#xff0c;很多注释是自己摸索得到。如有不正确的地方&#xff0c;敬请指正。 ! —————————————————————————— ! 1、为何需要…

PHP:isset()-检测变量是否被设置

isset()-检测变量是否被设置 bool isset(mixed $var [, mixed $...])&#xff0c;检查变量是否被设置&#xff0c;并且不是NULL。var,要检测的变量&#xff0c;...其他变量&#xff0c;允许有多个变量。 返回值&#xff1a;如果var存在并且不是NULL&#xff0c;则返回TRUE&…

Android通过ShareSDK实现新浪微博分享

ShareSDK社会化分享的官方说明&#xff1a;是中国最大的APP内分享服务提供商&#xff0c;ShareSDK社会化分享&#xff0c;全面支持微信&#xff0c;微博&#xff0c;QQ空间&#xff0c;来往&#xff0c;易信&#xff0c;Facebook等国内外40个平台。 ShareSDK官方网站&#xff…