Collection View

xib-based

Drag NSCollectionView control to xib interface from control libraries, change control custom class to component class name of your exported.

Unlike other controls, there are several initialization and configuration methods in the controller's viewDidLoad method. The detailed code is as follows:

import Cocoa
                        
 class ViewController: NSViewController {
    
    @IBOutlet weak var collectionView: HDCollectionView!

    var scrollDirection: NSCollectionView.ScrollDirection = .vertical {
        didSet {
            self.flowLayout.scrollDirection = scrollDirection
        }
    }
    
    var sectionInset: NSEdgeInsets = NSEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    
    var itemSize: NSSize = NSSize(width: 60, height: 60)
    var minimumLineSpacing: CGFloat = 10.0
    var minimumInteritemSpacing: CGFloat = 10.0
    
    var headerSize: NSSize = NSSize(width: 60, height: 60)
    var footerSize: NSSize = NSSize(width: 60, height: 60)
    
    var fillColor: NSColor? {
        didSet {
            if let fillColor = fillColor {
                collectionView.backgroundColors[0] = fillColor
            }
        }
    }
    
    var itemFillColor: NSColor?
    var itemFillGradient: NSGradient?
    var itemHighlightFillColor: NSColor?
    var itemHighlightFillGradient: NSGradient?
    var itemHoverColor: NSColor?
    var itemHoverGradient: NSGradient?
    
    var itemBorderColor: NSColor?
    var itemBorderWidth: CGFloat?
    var itemBorderRadius: CGFloat?
    
    var itemHighlightBorderColor: NSColor?
    var itemHighlightBorderWidth: CGFloat?
    
    var items:[PageItem] = [PageItem]()
    

    
    lazy var flowLayout: NSCollectionViewFlowLayout = {
        let layout = NSCollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        layout.itemSize = self.itemSize
        layout.sectionInset = self.sectionInset
        layout.minimumInteritemSpacing = self.minimumInteritemSpacing
        layout.minimumLineSpacing = self.minimumLineSpacing
        return layout
    }()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //Style Config
        collectionViewStyleConfig()
        // Delegate
        collectionViewDelegateConfig()
        //Test Data Config
        configViewData()
    }
    
    func collectionViewDelegateConfig() {
        collectionView.delegate = self
        collectionView.dataSource = self
        
        collectionView.collectionViewLayout = self.flowLayout
        collectionView.register(HDCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: HDCollectionViewItem.reuseIdentifier))
    }
    
    func collectionViewStyleConfig() {
        self.scrollDirection = .vertical
        self.sectionInset = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0,right: 10.0)
        self.itemSize = NSSize(width: 60.0, height: 60.0)
        self.minimumLineSpacing = 10.0
        self.minimumInteritemSpacing = 10.0
        self.headerSize = NSSize(width: 60.0, height: 60.0)
        self.footerSize = NSSize(width: 60.0, height: 60.0)
        self.fillColor = NSColor(calibratedRed: 0.00, green: 0.22, blue: 0.28, alpha: 1.0)
        self.itemHoverColor = NSColor(calibratedRed: 0.02, green: 0.25, blue: 0.76, alpha: 1.0)
        self.itemBorderColor = NSColor(calibratedRed: 0.99, green: 0.02, blue: 0.51, alpha: 1.0)
        self.itemBorderWidth = 2.0
        self.itemBorderRadius = 2.0
        self.itemHighlightBorderColor = NSColor(calibratedRed: 0.00, green: 0.64, blue: 0.83, alpha: 1.0)
    }
    
    func configViewData() {
        let colorItems:[ColorItem] = [
            ("Default", NSColor(hex: 0x33495e)),
            ("Action",  NSColor(hex: 0x33BFFD)),
            ("Cancel",  NSColor(hex: 0xFF3692)),
            ("Primary", NSColor(hex: 0x1ABC9C)),
            ("Info",    NSColor(hex: 0x3498DB)),
            ("Danger",  NSColor(hex: 0xE74C3C)),
            ("Sucess",  NSColor(hex: 0x2ECC71)),
            ("Warning", NSColor(hex: 0xF1C40F)),
            ("Inverse", NSColor(hex: 0x34495E)),
            ("Disabled",NSColor(hex: 0xBAC4C5)),
            ]
        
        var items:[PageItem] =  [PageItem]()
        for item:(name: String,color: NSColor?)  in colorItems {
            let image = NSImage(color: item.color!, size: NSMakeSize(60, 30) , radius: 4)
            items.append((item.name,image))
        }
        self.items = items
        self.collectionView.reloadData()
    }
}


extension ViewController : NSCollectionViewDataSource {
    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }
    
    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
        
        let  reuseIdentifier = HDCollectionViewItem.reuseIdentifier
        let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: reuseIdentifier), for: indexPath)
        
        guard let pageItem = item as? HDCollectionViewItem else { return item }
        
        let image = items[indexPath.item].image
        pageItem.image = image
        pageItem.textField?.stringValue = "\(indexPath.item + 1)"
        
        updatePageItem(item: pageItem)
        
        
        var highlight = false
        let selectedIndex = collectionView.selectionIndexPaths.first
        if selectedIndex == indexPath { highlight = true }
        pageItem.setHighlight(highlight)
        
        return pageItem
    }
    
    func updatePageItem(item: HDCollectionViewItem) {
        item.borderColor    = itemBorderColor
        item.borderWidth    = itemBorderWidth
        item.borderRadius   = itemBorderRadius
        item.fillColor      = itemFillColor
        item.fillGradient   = itemFillGradient
        item.hoverColor     = itemHoverColor
        item.hoverGradient  = itemHoverGradient
        
        item.highlightBorderColor    = itemHighlightBorderColor
        item.highlightBorderWidth    = itemHighlightBorderWidth
        item.highlightFillColor      = itemHighlightFillColor
        item.highlightFillGradient   = itemHighlightFillGradient
    }
}

extension ViewController : NSCollectionViewDelegate {
    func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set) {
        
        guard let indexPath = indexPaths.first else {
            return
        }
        guard let pageItem = collectionView.item(at: indexPath) as? HDCollectionViewItem  else {
            return
        }
        updatePageItem(item: pageItem)
        pageItem.setHighlight(true)
    }
    
    func collectionView(_ collectionView: NSCollectionView, didDeselectItemsAt indexPaths: Set) {
        guard let indexPath = indexPaths.first else { return }
        guard let pageItem = collectionView.item(at: indexPath) as? HDCollectionViewItem else {
            return
        }
        updatePageItem(item: pageItem)
        pageItem.setHighlight(false)
    }
}

code-based

Declare lazy load variable collectionView and scrollView in the controller class , add scrollView to the view. implement several initialization and configuration methods in the controller's viewDidLoad method. The detailed code is as follows:

import Cocoa
class ViewController: NSViewController  {
    
    var scrollDirection: NSCollectionView.ScrollDirection = .vertical {
        didSet {
            self.flowLayout.scrollDirection = scrollDirection
        }
    }
    
    var sectionInset: NSEdgeInsets = NSEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    
    var itemSize: NSSize = NSSize(width: 60, height: 60)
    var minimumLineSpacing: CGFloat = 10.0
    var minimumInteritemSpacing: CGFloat = 10.0
    
    var headerSize: NSSize = NSSize(width: 60, height: 60)
    var footerSize: NSSize = NSSize(width: 60, height: 60)
    
    var fillColor: NSColor? {
        didSet {
            if let fillColor = fillColor {
                collectionView.backgroundColors[0] = fillColor
            }
        }
    }
    
    var itemFillColor: NSColor?
    var itemFillGradient: NSGradient?
    var itemHighlightFillColor: NSColor?
    var itemHighlightFillGradient: NSGradient?
    var itemHoverColor: NSColor?
    var itemHoverGradient: NSGradient?
    
    var itemBorderColor: NSColor?
    var itemBorderWidth: CGFloat?
    var itemBorderRadius: CGFloat?
    
    var itemHighlightBorderColor: NSColor?
    var itemHighlightBorderWidth: CGFloat?
    
    var items:[PageItem] = [PageItem]()
    
    lazy var collectionView: HDCollectionView = {
        let view = HDCollectionView()
        view.isSelectable = true
        view.delegate     = self
        view.dataSource   = self
        view.collectionViewLayout = self.flowLayout
        view.register(HDCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: HDCollectionViewItem.reuseIdentifier))
        view.backgroundColors[0] = NSColor.windowBackgroundColor
        return view
    }()
    
    lazy var flowLayout: NSCollectionViewFlowLayout = {
        let layout = NSCollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        layout.itemSize = self.itemSize
        layout.sectionInset = self.sectionInset
        layout.minimumInteritemSpacing = self.minimumInteritemSpacing
        layout.minimumLineSpacing = self.minimumLineSpacing
        return layout
    }()
    
    lazy var scrollView: NSScrollView = {
        let scrollView = NSScrollView()
        scrollView.focusRingType = .none
        scrollView.autohidesScrollers = true
        scrollView.borderType = .noBorder
        scrollView.backgroundColor = NSColor.red
        scrollView.documentView = self.collectionView
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        return scrollView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //Style Config
        collectionViewStyleConfig()
        //Add Subview
        addTabView()
        //Set AutoLayout
        setupAutolayout()
        //Test Data Config
        configViewData()
    }
    
    func addTabView() {
        self.view.addSubview(scrollView)
    }
    
    func setupAutolayout() {
        scrollView.left = 10
        scrollView.right = -10
        scrollView.top = 10
        scrollView.bottom = -10
    }
    
    func collectionViewStyleConfig() {
        self.scrollDirection = .horizontal
        self.sectionInset = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0,right: 10.0)
        self.itemSize = NSSize(width: 60.0, height: 60.0)
        self.minimumLineSpacing = 10.0
        self.minimumInteritemSpacing = 10.0
        self.headerSize = NSSize(width: 60.0, height: 60.0)
        self.footerSize = NSSize(width: 60.0, height: 60.0)
        self.fillColor = NSColor(calibratedRed: 1.00, green: 1.00, blue: 1.00, alpha: 1.0)
        self.itemHoverColor = NSColor(calibratedRed: 0.02, green: 0.26, blue: 0.76, alpha: 1.0)
    }
    
    func configViewData() {
        let colorItems:[ColorItem] = [
        ("Default", NSColor(hex: 0x33495e)),
        ("Action",  NSColor(hex: 0x33BFFD)),
        ("Cancel",  NSColor(hex: 0xFF3692)),
        ("Primary", NSColor(hex: 0x1ABC9C)),
        ("Info",    NSColor(hex: 0x3498DB)),
        ("Danger",  NSColor(hex: 0xE74C3C)),
        ("Sucess",  NSColor(hex: 0x2ECC71)),
        ("Warning", NSColor(hex: 0xF1C40F)),
        ("Inverse", NSColor(hex: 0x34495E)),
        ("Disabled",NSColor(hex: 0xBAC4C5)),
        ]
        
        var items:[PageItem] =  [PageItem]()
        for item:(name: String,color: NSColor?)  in colorItems {
            let image = NSImage(color: item.color!, size: NSMakeSize(60, 30) , radius: 4)
            items.append((item.name,image))
        }
        self.items = items
        self.collectionView.reloadData()
    }
}


extension ViewController : NSCollectionViewDataSource {
    func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }
    
    func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
        
        let  reuseIdentifier = HDCollectionViewItem.reuseIdentifier
        let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: reuseIdentifier), for: indexPath)
        
        guard let pageItem = item as? HDCollectionViewItem else { return item }
        
        let image = items[indexPath.item].image
        pageItem.image = image
        pageItem.textField?.stringValue = "\(indexPath.item + 1)"
        
        updatePageItem(item: pageItem)
        
        
        var highlight = false
        let selectedIndex = collectionView.selectionIndexPaths.first
        if selectedIndex == indexPath { highlight = true }
        pageItem.setHighlight(highlight)
        
        return pageItem
    }
    
    func updatePageItem(item: HDCollectionViewItem) {
        
        item.borderColor    = itemBorderColor
        item.borderWidth    = itemBorderWidth
        item.borderRadius   = itemBorderRadius
        item.fillColor      = itemFillColor
        item.fillGradient   = itemFillGradient
        item.hoverColor     = itemHoverColor
        item.hoverGradient  = itemHoverGradient
        
        item.highlightBorderColor    = itemHighlightBorderColor
        item.highlightBorderWidth    = itemHighlightBorderWidth
        item.highlightFillColor      = itemHighlightFillColor
        item.highlightFillGradient   = itemHighlightFillGradient
    }
}

extension ViewController : NSCollectionViewDelegate {
    func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set) {
        
        guard let indexPath = indexPaths.first else {
            return
        }
        guard let pageItem = collectionView.item(at: indexPath) as? HDCollectionViewItem  else {
            return
        }
        updatePageItem(item: pageItem)
        pageItem.setHighlight(true)
    }
    
    func collectionView(_ collectionView: NSCollectionView, didDeselectItemsAt indexPaths: Set) {
        guard let indexPath = indexPaths.first else { return }
        guard let pageItem = collectionView.item(at: indexPath) as? HDCollectionViewItem else {
            return
        }
        updatePageItem(item: pageItem)
        pageItem.setHighlight(false)
    }
}