首页 > 解决方案 > NSCollectionView 作为 NSCollectionViewItem

问题描述

这是我想要实现的窗口: 实现窗口 它是一个以 NSCollectionView (RedCollectionView) 作为视图的 NSViewController (RedViewController)。
它的项目 (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. 带有 BlueCollectionView 的 BlueItem 没有得到预期的蓝色背景。 2. BlueCollectionView 流布局尝试在第一行显示所有项目。看起来它不知道集合视图的大小。 3. 当我尝试选择一个BlueItem 时:如果我点击BlueItem 内的空白区域,RedCollectionView 委托会按预期触发,但如果我点击BlueItem 内的绿色部分,则不会触发RedCollectionView 委托。应用截图




标签: nscollectionviewnscollectionviewitemnscollectionviewlayout

解决方案


推荐阅读