原文地址 翻译:DeveloperLx
collection view对可视化布局一系列有序的数据项目,是一个非常强有力的机制。用技术术语来进行解释会非常地无聊,因此考虑类似这些app:Finder和Photos;这些app让你在一个“画廊布局”下浏览文件。
在OS X 10.5发布时,
NSCollectionView
提供了一个便利的手段,那就是在一个可滚动的view上,用网格式的相同尺寸的项目,来排列一组对象。
OS X 10.11,也就是El Capitan,受iOS中的
UICollectionView
启发,对El Capitan进行了一次大修改。
除其它方面之外,新的
NSCollectionView
API添加了以下的支持:
- 带有可选的header/footer的section
- 可变尺寸的项目
- 可定制的布局
- 可重用的Cell
在这个OS X的collection view的教程中,你将会发现用漂亮流动的界面对桌面进行布局的乐趣。你将会关闭UX在移动和桌面之间的隔阂,并通过构建 SlidesMagic - 你自己的基于网格的图片浏览app,享受到对你的app更棒的控制。
这篇教程假定你已了解编写OS X app的基本技能。如果你是一个OS X的新手,你可以先学习一下这里的 OS X教程 然后再回来学习collection view。
表演马上要开始了!所以找一个座位,准备好你自己的有关
NSCollectionView
的个人魔术表演。
NSCollectionView
是主要的view - 也就是魔法将会发生的舞台。它展示了可见的项目,并包含了这些关键的成分:
NSCollectionViewLayout
- 这个版本中的新内容,让你可以通过设置collection
view的
collectionViewLayout
来指定一个布局。它是一个抽象类,所有实际的布局的类都继承自它。
NSCollectionViewFlowLayout
- 提供了一个灵活的网格布局,对于大多数的app,你都可以达到你所期望的结果。
NSCollectionViewGridLayout
- 匹配
NSCollectionView
的简单的OS X 10.11前的网格布局的行为,但不支持部分和所有新的API带来的好东西。
Section和
NSIndexPath
- 可以把项目分组成section。这些项目就构成了一个section的有序列表,每个section则包含一个有序的项目列表。每个项目都被关联到一个被封装到一个包含一堆整数(section,item)的
NSIndexPath
的实例中。
当需求并非是将项目分组到一个个section中时,默认你仍然含有至少一个section。
.
就像很多其它的 Cocoa 框架一样,collection view的项目遵循 MVC 设计模式。
Model和View - item的内容来自你的model的数据对象。每个单独的对象都从大的collection view中得到了它自己的view,进而变得可视化。这些单独的view的结构都被定义到了一个单独的nib文件中(扩展名为“.xib”)。
Controller
- 上面提到的nib文件是由一个
NSCollectionViewItem
的实例持有的,它是一个
NSViewController
或其子类的节点。它协调了在item和model对象中的信息流。通常,你会继承
NSCollectionViewItem
。当item并非相同的类型时,你就要为每种类型定义不同的子类和nib。
为了展示在collection view中不属于任一item的额外信息,你将使用supplementary view;对于这些一些共同的实现,就是section的header和footer了。
-
NSCollectionViewDataSource
- 是在 OS X 10.11 引入的新API,它会使用item和supplementary填充collection view。 -
NSCollectionViewDelegate
- 处理有关拖拽,选择和高亮的事件。 -
NSCollectionViewDelegateFlowLayout
- 让你可以定制一个流式布局。
SlidesMagic 你将要构建的app是一个图片浏览器。它相当得酷,但你不要太过兴奋把你的Mac中的照片都删掉了。
它会检索文件系统中的一个目录的所有图片文件,并展示它们及其名字到一个优雅的collection view上。当你想象它的时候,它其实是一种神奇的东西!完成的app看起来将会是这样:
在 这里 下载起始项目,并在Xcode Xcode 中打开它。运行项目:
现在出现了一个空的窗口,但它包含隐藏的特性,它将会成为图片浏览器的基础。
当 SlidesMagic 运行时,它会从系统的 Desktop Pictures 目录中自动地加载全部的图片。从 Xcode 的控制log中,你可以看到文件的名称。
在控制台中的这个列表是模型逻辑加载完毕的指示器。你可以通过选择 File \ Open Another Folder… 菜单来选择另一个目录。
启动项目提供了并非和collocation view直接相关,但特定于 SlidesMagic 的功能。
- ImageFile.swift :封装了一个单独的图片文件
- ImageDirectoryLoader.swift :用来从磁盘中加载图片的助手类
app有两个主要的controller:
-
WindowController.swift
-
windowDidLoad()
负责初始化屏幕左侧窗口的尺寸。openAnotherFolder
方法是由 File \ Open Another Folder… 菜单项调用的,它代表一个标准的打开对话框来选择不同的目录。 -
ViewController.swift
–
viewDidLoad()
打开了桌面的图片目录作为待浏览的初始目录,而loadDataForNewFolderWithUrl()
是通过来自WindowController
的openAnotherFolder
使用的。
打开 Main.storyboard 。找到 Object Library ,并拖拽一个 Collection View 到 View Controller Scene 的view上。
如果你现在build,你会看到一个错误:
Main.storyboard: Unknown segue relationship: Prototype
和collection view一起,
Xcode
还添加了一个
NSCollectionViewItem
,且于一个
Prototype
segue相连。
这其中就有造成了你build错误的原因 - 这就是造成这种麻烦的segue的类型。这是一个OS X 10.10的遗产(或是一个bug如果你喜欢的话),早期的API model可以避免你在storyboard中使用collection view item。
修复的方法是删除它,并将它转化为一个独立的 xib 文件。
选择 Collection View Item 并按 Delete 键来删除它。
现在错误就消失了。
调整 Bordered Scroll View 的大小,让它可以占据整个父view的区域。然后,选择 Editor \ Resolve Auto Layout Issues \ Add Missing Constraints 来添加 Auto Layout 约束。
你需要在
ViewController
添加一个outlet来连接collection view。打开
ViewController.swift
并添加下列的代码到
ViewController
类的定义中:
@IBOutlet weak var collectionView: NSCollectionView!
打开 Main.storyboard ,并选择 View Controller Scene 中的 View Controller 。
打开 Connections Inspector 并在 Outlets 部分找到 collectionView 元素。通过 拖拽 画布上靠近collection view控件的button到collection view来进行连接。
你已获得了选项:你可以获取初始的布局,和一些 Interface Builder 中的attribute,或者你可以用编程方式来设置它们。
对于,你将采用编程的方式。
打开
ViewController.swift
并添加下列的方法到
ViewController
:
private func configureCollectionView() {
// 1
let flowLayout = NSCollectionViewFlowLayout()
flowLayout.itemSize = NSSize(width: 160.0, height: 140.0)
flowLayout.sectionInset = NSEdgeInsets(top: 10.0, left: 20.0, bottom: 10.0, right: 20.0)
flowLayout.minimumInteritemSpacing = 20.0
flowLayout.minimumLineSpacing = 20.0
collectionView.collectionViewLayout = flowLayout
// 2
view.wantsLayer = true
// 3
collectionView.layer?.backgroundColor = NSColor.blackColor().CGColor
}
以上代码完成了:
-
创建一个
NSCollectionViewFlowLayout
并设置它的attribute,以及NSCollectionView
的collectionViewLayout
property。 -
为了优化性能,
NSCollectionView
被设计为基于layer的。因此,你要设置其wantsLayer
property为true
。 - 建立一个对于layer的特定于 SlidesMagic 的额外的关联,设置collection view的北京颜色为黑色。
你需要在view被创建时调用这个方法,因此添加下列的代码到
viewDidLoad()
的尾部:
configureCollectionView()
运行项目:
现在,你已经有了一个黑色的背景和布局。你已经为你的魔法show设置好了舞台!
为了加载项目,你需要调用这个
reloadData()
方法,它会让collection view重新展示当前可见的item。
你通常会在model发生变化时调用这个方法。
打开
ViewController.swift
并添加下列的代码到
loadDataForNewFolderWithUrl(\_:)
的尾部:
collectionView.reloadData()
这让它可以通过选择
File \ Open Another Folder…
来调用这个方法。它会加载一个新的model,然后调用
reloadData()
。
由于你从storyboard移除
NSCollectionViewItem
并不意味着你不需要它。:] 这里是如何将它带回来的正确方式。
前往 File \ New \ File… ,选择 OS X \ Source \ Cocoa Class 并单击 Next 。
设置
Class
域为
CollectionViewItem
,它是
NSCollectionViewItem
的
子类
,并单击
Also create XIB for user interface
。
单击 Next ,在保存对话框中,从 Group 选择 Controllers 并单击 Create 。
打开 CollectionViewItem.swift 并使用下列代码替换整个类:
class CollectionViewItem: NSCollectionViewItem {
// 1
var imageFile: ImageFile? {
didSet {
guard viewLoaded else { return }
if let imageFile = imageFile {
imageView?.image = imageFile.thumbnail
textField?.stringValue = imageFile.fileName
} else {
imageView?.image = nil
textField?.stringValue = ""
}
}
}
// 2
override func viewDidLoad() {
super.viewDidLoad()
view.wantsLayer = true
view.layer?.backgroundColor = NSColor.lightGrayColor().CGColor
}
}
在,这里:
-
定义
imageFile
property来持有将在这个item中展示的model对象。当设置的时候,它的didSet
property观察者就会设置item的图片和标签内容。 - 改变item的view的背景颜色。
在nib文件中的 View ,是在item中展示的控件树的根view。你将会添加一个image view,和一个用来展示文件名的label。
打开 CollectionViewItem.xib 。
添加一个
NSImageView
:
- 从 Object Library 中,添加一个 Image View 到 View 上。
- 选择并从 Auto Layout 的工具栏中单击 Pin 来设置它的约束。
- 设置 top , leading 和 trailing 约束为0, bottom 为30并单击 Add 4 Constraints 。
- 为了修复这个Auto Layout的问题,选择 Editor \ Resolve Auto Layout Issues \ Update Frames 。
添加一个label:
- 从 Object Library 中,添加一个 Label 到 Image View 下面。
- 单击 Pin 按钮。设置 top , bottom , trailing 和 leading 约束为0,然后单击 Add 4 Constraints 。
- 选择 Editor \ Resolve Auto Layout Issues \ Update Frames 来更新它的位置。
选择 Label ,在 Attributes Inspector 中设置下列的attribute:
- Alignment 为 center
- Text Color 为 white
- Line Break 为 Truncate Tail
现在你需要连接控件到
imageView
和
textField
的outlets上:
- 选择 File’s Owner 并展示 Connections Inspector 。
- 接下来,将靠近 imageView 的按钮 拖拽到 Image View 控件上,并连接它们。
-
用相同的方式,连接
textField
的outlet到 Label 上。
在nib文件中的
File’s Owner
- 它的类型是
CollectionViewItem
- 只是一个占位符。你仍然需要去实例化它。
CollectionView
的方法
makeItemWithIdentifier(\_:forIndexPath:)
会实例化collection view的item,它要求nib文件包含一个单独的顶层的
NSCollectionViewItem
的实例或它的子类。
你需要让它显示出来。
从
Object Library
中拖拽一个
Collection View Item
并将它放置到
Document Outline
中。选择它,并在
Identity Inspector
中,设置它的
Class
为
CollectionViewItem
。
你需要实现data source的方法,让Collection View可以了解下列内容:
- 在collection中有多少个section?
- 在每个section中有多少个item?
- 哪个item和指定的索引路径相关联?
满足你的data source方法:
NSCollectionViewDataSource
协议。
现在进入实践 - 打开 ViewController.swift 并添加下列的extension到文件的尾部:
extension ViewController : NSCollectionViewDataSource {
// 1
func numberOfSectionsInCollectionView(collectionView: NSCollectionView) -> Int {
return imageDirectoryLoader.numberOfSections
}
// 2
func collectionView(collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return imageDirectoryLoader.numberOfItemsInSection(section)
}
// 3
func collectionView(collectionView: NSCollectionView, itemForRepresentedObjectAtIndexPath indexPath: NSIndexPath) -> NSCollectionViewItem {
// 4
let item = collectionView.makeItemWithIdentifier("CollectionViewItem", forIndexPath: indexPath)
guard let collectionViewItem = item as? CollectionViewItem else {return item}
// 5
let imageFile = imageDirectoryLoader.imageFileForIndexPath(indexPath)
collectionViewItem.imageFile = imageFile
return item
}
}
-
这个方法提供了section的数量。当你的app不支持section的时候,你可以忽略这个方法,collection view就会只有一个section。当
SlidesMagic
启动的时候,model
imageDirectoryLoader
会被设置返回值为1。 -
这是
NSCollectionViewDataSource
中的两个必须方法之一。在这里,你要返回由section
参数所指定的section中的item的数量。在启动的时候 SlidesMagic 有一个单独的section,因此你设置让model来返回目录中image的总数。 -
这是第二个必须的方法。它对于给定的
indexPath
,返回一个collection view的item。 -
collection view的方法
makeItemWithIdentifier(_:forIndexPath:)
从nib文件中初始化了一个item,该nib文件的名称和identifier
参数相同。在本例中,它是“CollectionViewItem”
。首先,它尝试去复用一个要求类型的未使用的item,如果没有的话,它就会创建一个新的。 -
此代码根据给定的
NSIndexPath
得到相应的model对象,并设置图片和标签的内容。
没有数据的collection view就像是一个“没有灵巧的手的魔法表演” - 毫无生趣。因此,下一步就是定义data source了。在本案中它就是view controller。
打开 Main.storyboard 并选择collection view。
打开 Connections Inspector 并在 Outlets 部分找到 dataSource 。 拖拽 临近的按钮到 Document Outline View 中的 View Controller 上。
看!对得起全部的工作!你的collection view展示了来自 Desktop Pictures 目录中的图片!
如果你不能看到图片,然后某些事发生了错误。你已经通过了几个步骤,因此你只是犯了一些小错误。
- 所有的 Connections Inspector 是否已按照教程设置?
-
你是否设置了
dataSource
outlet? - 你是否在 Identity Inspector 中使用了正确的定制的类。
-
你是否添加了顶层的
NSCollectionViewItem
的对象,并将它的类型改变为CollectionViewItem
? -
在
makeItemWithIdentifier
中identifier
参数的值是否相等于nib的名称?
MagicSlides现在正在认真地表演魔法。但你还想通过添加一些section来提高它。
首先,你需要在view的底部添加一个check box,让你可以在单section和多section之间切换。
打开 Main.storyboard ,并在 Document Outline view中,选择scroll view的底部约束。打开 Size Inspector 并将 Constant 改变为30。
这样你就将collection view向上移动了一些,并给check box留出了空间。
现在,从 Object Library 中拖拽一个 Check Box Button 到collection view的下方。选择它,并在 Attributes Inspector 中,设置 Title 为 Show Sections , State 为 Off 。
然后,通过选择 Editor \ Resolve Auto Layout Issues \ Add Missing Constraints 菜单项设置 Auto Layout 约束。
运行项目。它的底部应当看起来就像这样:
现在是一个小UI。当你单击box时,app需要改变collection view的外观。
打开
ViewController.swift
并添加下列的方法到
ViewController
类的尾部:
// 1
@IBAction func showHideSections(sender: AnyObject) {
// 2
let show = (sender as! NSButton).state
imageDirectoryLoader.singleSectionMode = (show == NSOffState)
imageDirectoryLoader.setupDataForUrls(nil)
// 3
collectionView.reloadData()
}
一部分一部分地说,这里是你所做的事:
- 通过切换checkbox的状态来调用这个方法。
-
相应地,检索checkbox的状态,并设置数据model的mode为
singleSelectionMode
,然后调用model的setupDataForUrls(_:)
方法来重新排列section的结构。传递nil
的值则意味着你跳过了图片的加载 - 相同的图片,不同的布局。
如果你好奇于图片是如何通过section进行分布,可查阅
ImageDirectoryLoader
中的
sectionLengthArray
。在这个数组中元素的数量,就被设定成了section的最大数量,元素的值则设定了在每一section中item的数量。
现在,打开 Main.storyboard 。在 Document Outline 中, 按住Control拖拽 Show Sections 控件到 View Controller 上。在弹出的黑色菜单中,单击 showHideSections: 来连接它。你可以在 Connections Inspector 中查看connection是否被正确地设置。
运行项目。
查看 Show Sections ,并观察布局的变化。
由于第二行中的“黑色尾巴”,你会看到在第0部分有7个图像,但第1部分有5个图像,第2个部分则有10个(请看
sectionLengthArray
)。这并不清楚,因为这些section相当得懵逼。
要解决这个,打开
ViewController.swift
并在
configureCollectionView()
方法中修改布局的
sectionInset
property。
用:
flowLayout.sectionInset = NSEdgeInsets(top: 30.0, left: 20.0, bottom: 30.0, right: 20.0)
替换:
flowLayout.sectionInset = NSEdgeInsets(top: 10.0, left: 20.0, bottom: 10.0, right: 20.0)
在这里,你设置底部和顶部section的inset为30,以便提供更好的section之间的分隔。
运行项目:
查看 Show Sections ,注意到在section之间的额外的空间。
这个app到目前看起来都很棒,但更多的组织可以让它看起来更棒!
让section的边界看得更清楚的另一种方式,是添加一个header或footer。为实现这点,你需要添加一个定制的
NSView
类,以及实现一个data source的方法来提供header view到table view上。
为了创建header view,选择 File \ New \ File… 。选择 OS X \ User Interface \ View 并单击 Next 。
输入 HeaderView.xib 作为文件名称,对于 Group 则选择 Resources 。
单击 Create 。
打开 HeaderView.xib 并选择 Custom View 。打开 Size Inspector ,并改变 Width 为500以及 Height 为40。
从 Object Library 中拖拽一个label到 Custom View 的左侧。打开 Attributes Inspector 并改变 Title 为 Section Number ,以及 Font Size 为 16 。
拖拽第二个label到 Custom View 的右边,并将 Title 改为 Images Count , Text Alignment 改为 Right 。
现在,选择 Editor \ Resolve Auto Layout Issues \ Add Missing Constraints 菜单来添加 Auto Layout 约束。
header view应当看起来就像这样:
随着界面已准备好显示时间,下一个任务就是为header view创建一个定制的view的子类。
选择 File \ New \ File… 来创建一个新的文件。
选择
OS X \ Source \ Cocoa Class
并将类命名为
HeaderView
,并让它成为
NSView
的子类。单击下一步,对于
Group
选择
Views
。单击
Create
。
打开 HeaderView.swift 并使用下列代码替换类的内容:
// 1
@IBOutlet weak var sectionTitle: NSTextField!
@IBOutlet weak var imageCount: NSTextField!
// 2
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
NSColor(calibratedWhite: 0.8 , alpha: 0.8).set()
NSRectFillUsingOperation(dirtyRect, NSCompositingOperation.CompositeSourceOver)
}
这里:
- 设置你用来连接到nib上的label的outlet。
- 绘制一个灰色的背景。
随着框架已到位,下一个任务就是改变nib文件去使用新的类,以及连接outlet到label上。
打开 HeaderView.xib 并选择 Custom View 。打开 Identity Inspector 。改变 Class 为 HeaderView 。
在 Document Outline view中, 按住Control单击 Header View 。在弹出的黑色窗口中,将 imageCount 拖拽 到画布的 Images Count label上来连接outlet。
为第二个label执行重复的操作,将 sectionTitle 拖拽到画布的 Section Number label上。
你的header view已准备就绪,你需要将它拖拽到collection view上来实现
collectionView(_:viewForSupplementaryElementOfKind:atIndexPath:)
方法。
打开
ViewController.swift
并添加下列的方法到
NSCollectionViewDataSource
到extension中:
func collectionView(collectionView: NSCollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> NSView {
// 1
let view = collectionView.makeSupplementaryViewOfKind(NSCollectionElementKindSectionHeader, withIdentifier: "HeaderView", forIndexPath: indexPath) as! HeaderView
// 2
view.sectionTitle.stringValue = "Section (indexPath.section)"
let numberOfItemsInSection = imageDirectoryLoader.numberOfItemsInSection(indexPath.section)
view.imageCount.stringValue = "(numberOfItemsInSection) image files"
return view
}
collection view会在它需要data source为某个section提供header时,调用这个方法。方法:
-
调用
makeSupplementaryViewOfKind(_:withIdentifier:forIndexPath:)
方法来初始化一个withIdentifier
参数和nib名称相同的HeaderView
对象。 - 给label设置值。
在
ViewController.swift
的尾部,添加下列的
NSCollectionViewDelegateFlowLayout
extension。
extension ViewController : NSCollectionViewDelegateFlowLayout {
func collectionView(collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> NSSize {
return imageDirectoryLoader.singleSectionMode ? NSZeroSize : NSSize(width: 1000, height: 40)
}
}
以上的方法,在技术上也是可选的,但当你需要为每个section提供header的时候,你就必须使用它来为每个header提供尺寸的大小。
如果你没有实现,header就不会展示出来,因为它的尺寸会被认为是0。此外,它还会忽略指定的宽度,而是将宽度设置为collection view的宽度。
在本例中,这个方法会在collection view采取单个section模式时,返回尺寸为0;当collection view采取多section模式时,返回40。
为使collection view使用
NSCollectionViewDelegateFlowLayout
,你必须连接
ViewController
到
NSCollectionView
的outlet
delegate
上。
打开 Main.storyboard 并选择collection view。打开 Connections Inspector ,并在 Outlets 部分中找到 delegate 。将靠近它的按钮 拖拽 到 Document Outline 中的view controller。
运行项目。
查看 Show Sections ,并观察你的header已很好地区分了section。
Collection view支持单选和多选。为了表示item已被选取,你必须将它高亮一下。
在你行动之前,你必须让collection view变得可选。打开 Main.storyboard 。然后选择 Collection View ,并在 Attributes Inspector 中勾选 Selectable 。
勾选 Selectable 就可以打开单选,也就是你可以单击一个item来选择它。并且当你选择另一个item时,之前选择的那个就会被取消。
为了展示一个item已被选择,为它设置一个白色的边框,并使用
borderWith
将边框的粗细设定为5。未被选择的item则不会有特殊的处理。
打开
CollectionViewItem.swift
。添加下列代码到
viewDidLoad()
方法的尾部:
// 1
view.layer?.borderWidth = 0.0
// 2
view.layer?.borderColor = NSColor.whiteColor().CGColor
-
设定
borderWidth
为0.0
,即将item初始化为未被选择的状态 - 当item被选中时,设置为白色
添加下列的方法到
CollectionViewItem
类的尾部:
func setHighlight(selected: Bool) {
view.layer?.borderWidth = selected ? 5.0 : 0.0
}
这个方法是用来添加或移除高亮效果的。
当用户在collection view中选择了一个item,你就会从它的代理方法得到响应。你需要实现这些方法,因此,打开 ViewController.swift 并添加下列的extension到文件的尾部:
extension ViewController : NSCollectionViewDelegate {
// 1
func collectionView(collectionView: NSCollectionView, didSelectItemsAtIndexPaths indexPaths: Set<NSIndexPath>) {
// 2
guard let indexPath = indexPaths.first else {
return
}
// 3
guard let item = collectionView.itemAtIndexPath(indexPath) else {
return
}
(item as! CollectionViewItem).setHighlight(true)
}
// 4
func collectionView(collectionView: NSCollectionView, didDeselectItemsAtIndexPaths indexPaths: Set<NSIndexPath>) {
guard let indexPath = indexPaths.first else {
return
}
guard let item = collectionView.itemAtIndexPath(indexPath) else {
return
}
(item as! CollectionViewItem).setHighlight(false)
}
}
这就实现了必须的
NSCollectionViewDelegate
方法。更多细节:
-
当你选择了一个item,
NSCollectionView
就会调用这个方法。 - 这里你获得了被选择的item - 由于多选是被禁用的,它总是第一个。
- 通过序号来检索到item,并将它高亮。
- 就像上一个方法一样,但它是在item被取消选择是调用的。
当被选择时,item就被设置了:
-
加入
NSCollectionView
的propertyselectionIndexPaths
。 -
NSCollectionViewItem
的propertyselected
被设置为YES。
理解当
NSCollectionViewItem
的实例被循环使用时,它的数据必须被来自新的对象的数据刷新是非常
重要的
。你
NSCollectionViewItem
的property
selected
就是确保这点的地方。
因此,在
NSCollectionViewDataSource
的extension中,你需要添加下列的代码到
collectionView(_:itemForRepresentedObjectAtIndexPath:)
方法中,就在
return
语句之前:
if let selectedIndexPath = collectionView.selectionIndexPaths.first where selectedIndexPath == indexPath {
collectionViewItem.setHighlight(true)
} else {
collectionViewItem.setHighlight(false)
}
这就确保了选择和高亮是同步的。
运行项目。
点击一个item,你会看到高亮的效果。选择一个不同的图片,你就会看到完全的高亮功能。哇!真是魔术!
在
这里
可以下载到最终版本的
SlidesMagic
。
在这个OS X的collection view教程中,你从创建第一个collection view,到发掘了带有section的复杂的data sourc API,到使用代理协议来处理选择。然而,尽管你已了解了很多基础的内容,你仍然只是探索到了collection view能力的皮毛。例如,下面的内容你还并不了解:
- 使用Cocoa Bindings的“Data Source-less”的collection view
- 不同类型的item
- 添加和删除item
- 定制布局
- 拖拽和放置
- 动画
-
调整
NSCollectionViewFlowLayout
(例如,粘性的header)
我们将会覆盖其中的一些话题在 raywenderlich.com 的即将到来的OS X教程中,因此,这几个月记得常来看看。
有点不幸的是,来自苹果和其它来源的collection view的文档是非常有限的,但以下是我的建议:
- WWDC 2015 – Session 225 – What’s New in NSCollectionView
- OS X 10.11 El Capitan Release Notes for Cocoa Application Framework
- CocoaSlideCollection – Sample code of WWDC Session 225 above. Written in Objective-C
-
Exhibition
– Sample code from Apple, written in Swift using
NSCollectionViewGridLayout