NSCollectionView как NSCollectionViewItem
Вот окно, которое я хочу достичь: Это NSViewController (RedViewController) с NSCollectionView (RedCollectionView) в качестве представления.
Это элемент (BlueItem) имеет NSCollectionView (BlueCollectionView) в качестве представления.
Это элемент элемента (GreenItem), имеет NSImageView (GreenImageView) в качестве представления.
RedCollectionView будет прокручиваться вертикально, и его элементы будут доступны для выбора. Однако BlueCollectionView предназначен только для отображения, он не прокручивается сам по себе и не может быть выбран.
Вот код для AppDelegate:
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
lazy var redViewController: RedViewController = {
let redViewController = RedViewController.init()
return redViewController
}()
lazy var window: NSWindow = {
let window = NSWindow.init(contentViewController: self.redViewController)
return window
}()
lazy var windowController: NSWindowController = {
let windowController = NSWindowController.init(window: self.window)
return windowController
}()
func applicationDidFinishLaunching(_ aNotification: Notification) {
self.windowController.showWindow(nil)
}
}
Вот код для RedViewController:
class RedViewController: NSViewController, NSCollectionViewDataSource, NSCollectionViewDelegate {
lazy var collectionViewLayout: NSCollectionViewFlowLayout = {
let collectionViewLayout = NSCollectionViewFlowLayout.init()
collectionViewLayout.itemSize = NSSize(width: 100.0, height: 100.0)
collectionViewLayout.minimumLineSpacing = 10.0
collectionViewLayout.minimumInteritemSpacing = 10.0
collectionViewLayout.sectionInset = NSEdgeInsetsMake(10.0, 10.0, 10.0, 10.0)
return collectionViewLayout
}()
class RedCollectionView: NSCollectionView { /* nothing here for now */ }
lazy var redCollectionView: RedCollectionView = {
let redCollectionView = RedCollectionView.init(frame: NSRect(x: 0.0, y: 0.0, width: 500.0, height: 500.0))
redCollectionView.collectionViewLayout = self.collectionViewLayout
redCollectionView.dataSource = self
redCollectionView.delegate = self
redCollectionView.isSelectable = true
redCollectionView.backgroundColors = [NSColor.red]
return redCollectionView
}()
override func loadView() {
let clipView = NSClipView.init()
clipView.documentView = self.redCollectionView
let scrollView = NSScrollView.init(frame: NSRect(x: 0.0, y: 0.0, width: 500.0, height: 500.0))
scrollView.contentView = clipView
self.view = scrollView
}
override func viewDidLoad() {
super.viewDidLoad()
self.redCollectionView.register(BlueItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier("BlueItemID"))
}
func numberOfSections(in collectionView: NSCollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return 50
}
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "BlueItemID"), for: indexPath)
guard let blueItem = item as? BlueItem else { return item }
return blueItem
}
func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
indexPaths.forEach({ print($0) })
collectionView.deselectItems(at: indexPaths)
}
}
Вот код для BlueItem:
class BlueItem: NSCollectionViewItem, NSCollectionViewDataSource {
lazy var collectionViewLayout: NSCollectionViewFlowLayout = {
let collectionViewLayout = NSCollectionViewFlowLayout.init()
collectionViewLayout.itemSize = NSSize(width: 27.0, height: 27.0)
collectionViewLayout.minimumLineSpacing = 3.0
collectionViewLayout.minimumInteritemSpacing = 3.0
collectionViewLayout.sectionInset = NSEdgeInsetsMake(3.0, 3.0, 3.0, 3.0)
return collectionViewLayout
}()
class BlueCollectionView: NSCollectionView {
override func mouseDown(with event: NSEvent) {
super.mouseDown(with: event)
self.nextResponder?.mouseDown(with: event)
}
override func mouseUp(with event: NSEvent) {
super.mouseUp(with: event)
self.nextResponder?.mouseUp(with: event)
}
}
lazy var blueCollectionView: BlueCollectionView = {
let blueCollectionView = BlueCollectionView.init(frame: NSRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
blueCollectionView.collectionViewLayout = self.collectionViewLayout
blueCollectionView.dataSource = self
blueCollectionView.isSelectable = false
blueCollectionView.backgroundColors = [NSColor.blue]
return blueCollectionView
}()
override func loadView() {
self.view = self.blueCollectionView
}
override func viewDidLoad() {
super.viewDidLoad()
self.blueCollectionView.register(GreenItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier("GreenItemID"))
}
func numberOfSections(in collectionView: NSCollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return 7
}
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "GreenItemID"), for: indexPath)
guard let greenItem = item as? GreenItem else { return item }
return greenItem
}
}
И, наконец, вот код для GreenItem:
class GreenItem: NSCollectionViewItem {
class GreenImageView: NSImageView { /* nothing here for now */ }
lazy var greenImageView: GreenImageView = {
let image: NSImage = NSImage.init(imageLiteralResourceName: "greenImage")
let greenImageView = GreenImageView.init(image: image)
return greenImageView
}()
override func loadView() {
self.view = self.greenImageView
}
}
Когда я запускаю приложение, я получаю такой результат:
Итак, у меня есть 3 вопроса:
1. BlueItem с его BlueCollectionView не получает ожидаемый синий фон.
2. Макет потока BlueCollectionView пытается отобразить все элементы в первой строке. Похоже, он не знает размер представления коллекции.
3. Когда я пытаюсь выбрать BlueItem: если я щелкаю пустое пространство внутри BlueItem, делегат RedCollectionView запускается, как и ожидалось, но если я щелкаю зеленую часть внутри BlueItem, делегат RedCollectionView не запускается.