原文:UICollectionViews Now Have Easy Reordering

我是UICollectionView的忠实粉丝。这个类比起它的老哥UITableView类具有更高的可定制性。现在我用collection view的次数要比用table view还多。随着iOS9的到来,它支持简单的重排。在此之前,重排不可能有现成的方法,同时这样做也是件痛苦的工作。现在让我们来看看API,你可以在GitHub找到相应的Xcode工程

添加简单重排的最简单的方式是用UICollectionViewController。它现在有了一个新的属性叫installsStandardGestureForInteractiveMovement(为交互式移动工作设置标准手势),这个属性的添加使得我们可以用标准手势来对cell单元进行重新排序。该属性默认值为true,这意味着我们只需要重载一个方法就可以让它正常工作。

1
2
3
4
5
override func collectionView(collectionView: UICollectionView,
    moveItemAtIndexPath sourceIndexPath: NSIndexPath,
    toIndexPath destinationIndexPath: NSIndexPath) {
    // move your data order
}

Collection view推断每个item(元素)可以被移动,因为moveItemAtIndexPath函数被重载了。

当我们想使用一个带有collection view的简单的UIViewController时,事情变得更加复杂。我们还需要实现之前提到的UICollectionViewDataSource的方法,但我们需要重写installsStandardGestureForInteractiveMovement。别担心,这些也很容易被支持。UILongPressGestureRecognizer是一个持续的、完全支持平移的手势识别器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
override func viewDidLoad() {
    super.viewDidLoad()
     
            longPressGesture = UILongPressGestureRecognizer(target: self, action: "handleLongGesture:")
        self.collectionView.addGestureRecognizer(longPressGesture)
}
 
    func handleLongGesture(gesture: UILongPressGestureRecognizer) {
        switch(gesture.state) {
        case UIGestureRecognizerState.Began:
            guard let selectedIndexPath = self.collectionView.indexPathForItemAtPoint(gesture.locationInView(self.collectionView)) else {
                break
            }
            collectionView.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath)
        case UIGestureRecognizerState.Changed:
            collectionView.updateInteractiveMovementTargetPosition(gesture.locationInView(gesture.view!))
        case UIGestureRecognizerState.Ended:
            collectionView.endInteractiveMovement()
        default:
            collectionView.cancelInteractiveMovement()
        }
    }

我们储存了被选择的索引路径,这个路径从longPressGesture handler(长按手势处理器)中获得,这个路径还取决于它是否有任何我们允许的,跟平移手势相关的值。接下来我们根据手势状态调用一些新的collection view方法:

  • beginInteractiveMovementForItemAtIndexPath(indexPath: NSIndexPath)?开始在特定的索引路径上对cell(单元)进行Interactive Movement(交互式移动工作)。

  • updateInteractiveMovementTargetPosition(targetPosition: CGPoint)?在手势作用期间更新交互移动的目标位置。】

  • endInteractiveMovement()?在完成手势动作后,结束交互式移动

  • cancelInteractiveMovement()?取消Interactive Movement。

这让处理平移手势更容易理解了。

机器反应跟标准的UICollectionViewController一样,真的很酷,但是还有更酷的--我们能对自定义的collection view layout(collection集合视图布局)申请重排,下面是在waterfall layout(瀑布布局)里对Interactive Movement的测试。

嗯哼,看起来很酷,但如果我们不想在移动cell(单元)的时候改变它们的大小,那该怎么做?被选择的cell(单元)的大小在Interactive Movement期间应该保持原样。这是可行的。UICollectionViewLayout有附加的方法来处理重排。

1
2
3
4
5
6
7
8
func invalidationContextForInteractivelyMovingItems(targetIndexPaths: [NSIndexPath],
    withTargetPosition targetPosition: CGPoint,
    previousIndexPaths: [NSIndexPath],
    previousPosition: CGPoint) -> UICollectionViewLayoutInvalidationContext
     
func invalidationContextForEndingInteractiveMovementOfItemsToFinalIndexPaths(indexPaths: [NSIndexPath],
    previousIndexPaths: [NSIndexPath],
    movementCancelled: Bool) -> UICollectionViewLayoutInvalidationContext

第一个函数在元素的Interactive Movement期间被调用,它带有target(目标元素)和先前的cell的indexPaths(索引地址)。第二个与第一个函数类似,但它只在Interactive Movement结束后才调用。通过这些知识我们能通过一点小窍门,实现我们的需求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
internal override func invalidationContextForInteractivelyMovingItems(targetIndexPaths: [NSIndexPath],
    withTargetPosition targetPosition: CGPoint,
    previousIndexPaths: [NSIndexPath],
    previousPosition: CGPoint) -> UICollectionViewLayoutInvalidationContext {
     
    var context = super.invalidationContextForInteractivelyMovingItems(targetIndexPaths,
        withTargetPosition: targetPosition, previousIndexPaths: previousIndexPaths,
        previousPosition: previousPosition)
         
    self.delegate?.collectionView!(self.collectionView!, moveItemAtIndexPath: previousIndexPaths[0],
        toIndexPath: targetIndexPaths[0])
         
    return context
}

取得当前正在移动的cell的之前的和目标索引路径,然后调用UICollectionViewDataSource方法来移动这些item(元素)。

毫无疑问,collection view的重排是一个出色的附加功能,UIKit前端框架工程师干得漂亮!:)

P.S:我要感谢Douglas Hill对于代码完善的一些建议。

现在,UICollectionViews有了简单的重排功能的更多相关文章

  1. UICollectionViews有了简单的重排功能

    代码地址如下:http://www.demodashi.com/demo/13213.html 一.前言 我是UICollectionView的忠实粉丝.这个类比起它的老哥UITableView类具有 ...

  2. ASP.NET MVC 学习4、Controller中添加SearchIndex页面,实现简单的查询功能

    参考:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-edit-method ...

  3. Web---创建Servlet的3种方式、简单的用户注册功能

    说明: 创建Servlet的方式,在上篇博客中,已经用了方式1(实现Servlet接口),接下来本节讲的是另外2种方式. 上篇博客地址:http://blog.csdn.net/qq_26525215 ...

  4. js+html+css简单的互动功能页面(2015知道几乎尖笔试题)http://v.youku.com/v_show/id_XMTI0ODQ5NTAyOA==.html?from=y1.7-1.2

    js+html+css实现简单页面交互功能(2015知乎前端笔试题) http://v.youku.com/v_show/id_XMTI0ODQ5NTAyOA==.html? from=y1.7-1. ...

  5. Spring 学习——基于Spring WebSocket 和STOMP实现简单的聊天功能

    本篇主要讲解如何使用Spring websocket 和STOMP搭建一个简单的聊天功能项目,里面使用到的技术,如websocket和STOMP等会简单介绍,不会太深,如果对相关介绍不是很了解的,请自 ...

  6. Django文件上传三种方式以及简单预览功能

    主要内容: 一.文件长传的三种方式 二.简单预览功能实现 一.form表单上传 1.页面代码 <!DOCTYPE html> <html lang="en"> ...

  7. 运用socket实现简单的ssh功能

    在python socket知识点中已经对socket进行了初步的了解,那现在就使用这些知识来实现一个简单的ssh(Secure Shell)功能. 首先同样是建立两个端(服务器端和客户端) 需求是: ...

  8. Jenkins实现简单的CI功能

    步骤一:安装JDK.Tomcat,小儿科的东西不在此详细描述 步骤二:下载安装Jenkins下载链接:https://jenkins.io/download/ 步骤三:将下载的jenkins.war部 ...

  9. jQuery实现简单前端搜索功能

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. proc_dir_entry

    struct proc_dir_entry {        unsigned int low_ino;        unsigned short namelen;        const cha ...

  2. linux中压缩与解压缩命令小结

    linux中压缩与解压操作非常常见,其命令参数也非常的多,这里只介绍最经常用的带打包文件的几种压缩和解压方式和几个最常用的参数. 现在最常用的压缩和解压工具是gzip和bzip2,这两种工具不能相互解 ...

  3. oj放苹果

    题目描述 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. 输入 每个用例包含二个整数M和N.0<=m< ...

  4. 进程间通信机制<转>

    1   文件映射 文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待.因此,进程不必使用文件I/O操作,只需简单的指针操作就可读取和修改文件的内容. ...

  5. Jenkins iOS – Git, xcodebuild, TestFlight

    Introduction with Jenkins iOS If you are new to continuous integration for mobile platforms then you ...

  6. bzoj1412: [ZJOI2009]狼和羊的故事

    空地之间开始没有连然后一直WA...题意混乱...尴尬. #include<cstdio> #include<cstring> #include<iostream> ...

  7. 【ASP.NET】编程点滴 :ASP.NET身份验证

    ASP.NET实际开发中身份验证 是一个不可回避的问题.在相当一段长的时间内,由于不求甚解,我对这个话题似懂非懂.今天就对它做个简单的小结. Authentication and Authorizat ...

  8. 选择或者放弃MySQL的理由

    MySQL 作为一个开源数据库,自从被 Oracle 接管后,其发展前景就一直受到开发社区的关注,其中也有质疑,最近,两位开发者分别发表了选择和放弃MySQL 的理由,值得数据库相关人员参考. And ...

  9. poco网络库分析,教你如何学习使用开源库

    Poco::Net库中有 FTPClient HTML HTTP HTTPClient HTTPServer ICMP Logging Mail Messages NetCore NTP OAuth ...

  10. Maximum Product Subarray JAVA实现

    题目描述: Find the contiguous subarray within an array (containing at least one number) which has the la ...