OS X开发.第一章,1.7,NSCollectionView

1.7 NSCollectionView
NSCollectionView是Cocoa中用来展示多行多列的自定义Item的控件,其作用和写法类似于UICollectionView,均有数据源和代理协议构成,然而具体实现细节上却有很大出入,下面请看纯代码编写NSCollectionView的介绍,为了方便示例,本节内容并没有严格遵守MVC架构来进行。

1.7.1 基本声明
基本声明包括Item的创建、NSCollectionView的创建、NSCollectionFlowLayout的创建。这三者的创建细节与UICollectionView的细节上有着不同,请看下面讲解。

1.Item的创建
右键单击鼠标,选择New File->Cocoa Class->新建继承于NSCollectionViewItem的子类(取消勾选创建XIB文件),该类即我们的item子类布局文件。我们这里创建item内要有一个Label对象和一个NSImageView对象,其创建代码如下:

import Cocoa
import SnapKit

class CellItem: NSCollectionViewItem {
    
    var mView: NSView!
    var mImageView: NSImageView!
    var mLabel: NSTextField!
    
    override func loadView() {
        self.view = NSView(frame: NSRect(x: 0, y: 0, width: 100, height: 100))
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        installMImageView()
        installLabel()
    }
    
    private func installMImageView(){
        mImageView = NSImageView()
        self.view.addSubview(mImageView)
        
        mImageView.snp.makeConstraints{ make in
            make.size.equalTo(66)
            make.centerX.equalToSuperview()
            make.top.equalTo(self.view.snp.top).offset(15)
        }
    }
    
    private func installLabel(){
        mLabel = NSTextField()
        mLabel.drawsBackground = false
        mLabel.isBezeled = false
        mLabel.isEditable = false
        mLabel.alignment = .center
        self.view.addSubview(mLabel)
        
        mLabel.snp.makeConstraints{ make in
            make.width.equalTo(60)
            make.height.equalTo(25)
            make.top.equalTo(self.mImageView.snp.bottom).offset(2)
            make.centerX.equalToSuperview()
        }
    }
    
    public func updateView(){
        if self.isSelected == true {
            self.view.layer?.backgroundColor = .init(gray: 0.9, alpha: 0.9)
        } else if self.isSelected == false {
            self.view.layer?.backgroundColor = .white
        }
    }
}

说明:loadView()这个方法系纯代码创建要重写的方法,不重写系统则不会绘制此自定义NSView及其子类。

2.NSCollectionView的创建

    var mView: NSView!
    var scrollView: NSScrollView!
    var mCollectionView: NSCollectionView!
    
    override func loadView() {
        self.view = NSView(frame: NSRect(x: 0, y: 0, width: 500, height: 350))
    }
    
    private func initView(){
        mView = NSView(frame: NSRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
        
        scrollView = NSScrollView(frame: NSRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
        self.view.addSubview(scrollView)
        
        mCollectionView = NSCollectionView(frame: NSRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
        mCollectionView.delegate = self
        mCollectionView.dataSource = self
        mCollectionView.isSelectable = true
        mCollectionView.register(CellItem.self, forItemWithIdentifier:NSUserInterfaceItemIdentifier(rawValue: "NS_COLLECTION_VIEW"))
        self.scrollView.contentView.addSubview(mCollectionView)
    }

说明:在XIB中,创建的NSCollectionView对象实际上是置于NSScrollView上方,如果这里我们不手动创建一个NSScrollView对象,那么有关数据源代理方法实际上是不会执行的。

3.NSCollectionFlowLayout的创建
在上述的initView()方法内插入如下代码:

// ...
mCollectionView.isSelectable = true

let layout = NSCollectionViewFlowLayout()
layout.itemSize = .init(width: 100, height: 100)
layout.minimumLineSpacing = 10
layout.minimumInteritemSpacing = 10
mCollectionView.collectionViewLayout = layout

mCollectionView.register(CellItem.self, forItemWithIdentifier:NSUserInterfaceItemIdentifier(rawValue: "NS_COLLECTION_VIEW"))
// ...

1.7.2 数据源与代理协议
实现如下协议:

NSCollectionViewDataSource, NSCollectionViewDelegate

有关数据源和代理协议方法如下:

func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10 
} // 返回item数量
func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
        print("------> CLICK AT:\(indexPaths.first)")
        let view = collectionView.item(at: indexPaths.first!) as! CellItem
        view.updateView()
} // 对应的点击事件
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {      
	let view = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "NS_COLLECTION_VIEW"), for: indexPath) as! CellItem
        
	view.mImageView.image = NSImage(named: "user")
	view.mLabel.stringValue = "User"
        
	return view
} // 返回一个NSCollectionViewItem对象

本节代码:
CellItem.swift

import Cocoa
import SnapKit

class CellItem: NSCollectionViewItem {
    
    var mView: NSView!
    var mImageView: NSImageView!
    var mLabel: NSTextField!
    
    override func loadView() {
        self.view = NSView(frame: NSRect(x: 0, y: 0, width: 100, height: 100))
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        installMImageView()
        installLabel()
    }
    
    private func installMImageView(){
        mImageView = NSImageView()
        self.view.addSubview(mImageView)
        
        mImageView.snp.makeConstraints{ make in
            make.size.equalTo(66)
            make.centerX.equalToSuperview()
            make.top.equalTo(self.view.snp.top).offset(15)
        }
    }
    
    private func installLabel(){
        mLabel = NSTextField()
        mLabel.drawsBackground = false
        mLabel.isBezeled = false
        mLabel.isEditable = false
        mLabel.alignment = .center
        self.view.addSubview(mLabel)
        
        mLabel.snp.makeConstraints{ make in
            make.width.equalTo(60)
            make.height.equalTo(25)
            make.top.equalTo(self.mImageView.snp.bottom).offset(2)
            make.centerX.equalToSuperview()
        }
    }
    
    public func updateView(){
        if self.isSelected == true {
            self.view.layer?.backgroundColor = .init(gray: 0.9, alpha: 0.9)
        } else if self.isSelected == false {
            self.view.layer?.backgroundColor = .white
        }
    }
}

CollectionViewController.swift

//
//  CollectionViewController.swift
//  Versatile
//
//  Created by Eldest's MacBook on 2021/10/5.
//

import Cocoa
import SnapKit

class CollectionViewController: NSViewController, NSCollectionViewDataSource, NSCollectionViewDelegate {
    
    var mView: NSView!
    var scrollView: NSScrollView!
    var mCollectionView: NSCollectionView!
    
    override func loadView() {
        self.view = NSView(frame: NSRect(x: 0, y: 0, width: 500, height: 350))
    }
    
    private func initView(){
        mView = NSView(frame: NSRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
        
        scrollView = NSScrollView(frame: NSRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
        self.view.addSubview(scrollView)
        
        mCollectionView = NSCollectionView(frame: NSRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
        mCollectionView.delegate = self
        mCollectionView.dataSource = self
        mCollectionView.isSelectable = true
        let layout = NSCollectionViewFlowLayout()
        layout.itemSize = .init(width: 100, height: 100)
        layout.minimumLineSpacing = 10
        layout.minimumInteritemSpacing = 10
        mCollectionView.collectionViewLayout = layout
        mCollectionView.register(CellItem.self, forItemWithIdentifier:NSUserInterfaceItemIdentifier(rawValue: "NS_COLLECTION_VIEW"))
        self.scrollView.contentView.addSubview(mCollectionView)
    }
    
    private func initConfig(){
        self.title = "NSCollectionView"
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.
        
        initView()
        initConfig()
    }
    
    // MARK: - Delegate
    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }
    
    func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
        print("------> CLICK AT:\(indexPaths.first)")
        let view = collectionView.item(at: indexPaths.first!) as! CellItem
        view.updateView()
    }
    
    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
        
        let view = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "NS_COLLECTION_VIEW"), for: indexPath) as! CellItem
        
        view.mImageView.image = NSImage(named: "user")
        view.mLabel.stringValue = "User"
        
        return view
    }
}

运行截图:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值