Reputation: 1667
I am programmatically setting up a simple collection view but not seeing the insert/remove animations that I expected to get for free. I have checked out all methods on the classes associated with collection views and can't find anything that would seem to affect the animation. Is there something I am missing in this set-up please?
When inserting something at index 0 I am expecting to see the existing items move and a new item fading in.
class ECTestViewController: NSViewController
{
var scrollView: NSScrollView!
var collectionView: NSCollectionView!
var items = [Int]()
override func loadView() {
view = NSView()
view.translatesAutoresizingMaskIntoConstraints = false
}
override func viewDidLoad() {
super.viewDidLoad()
scrollView = NSScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
let scrollViewList = ["view": scrollView]
var scrollViewConstraints = NSLayoutConstraint.constraints(withVisualFormat: "|[view]|", metrics: nil, views: scrollViewList)
scrollViewConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-22-[view]-8-|", metrics: nil, views: scrollViewList)
NSLayoutConstraint.activate(scrollViewConstraints)
collectionView = NSCollectionView()
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.dataSource = self
collectionView.delegate = self
scrollView.documentView = collectionView
collectionView.collectionViewLayout = NSCollectionViewFlowLayout()
// Register the item types for the collection
collectionView.register(ECTestItem.self, forItemWithIdentifier: ECTestItem.interfaceIdentifier)
// Add our first item
items.append(0)
// Buttons to add and remove items
let openImage = NSImage(named: NSImage.Name("Open"))
let openButton = ECImageButton(image: openImage!)
view.addSubview(openButton)
openButton.action = #selector(openItem)
openButton.target = self
let closeImage = NSImage(named: NSImage.Name("Close"))
let closeButton = ECImageButton(image: closeImage!)
view.addSubview(closeButton)
closeButton.action = #selector(closeItem)
closeButton.target = self
}
@objc func closeItem() {
items.remove(at: 0)
collectionView.deleteItems(at: [IndexPath(item: 0, section: 0)])
}
@objc func openItem() {
items.insert(0, at: 0)
collectionView.insertItems(at: [IndexPath(item: 0, section: 0)])
}
}
extension ECTestViewController: NSCollectionViewDataSource
{
func numberOfSections(in collectionView: NSCollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
return collectionView.makeItem(withIdentifier: ECTestItem.interfaceIdentifier, for: indexPath)
}
}
extension ECTestViewController: NSCollectionViewDelegateFlowLayout // Actually set as the collection view delegate
{
func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
return NSMakeSize(100, 100)
}
}
class ECTestItem: NSCollectionViewItem
{
static var interfaceIdentifier: NSUserInterfaceItemIdentifier { get { return NSUserInterfaceItemIdentifier("ouliner") } }
override func loadView() {
view = NSView()
view.translatesAutoresizingMaskIntoConstraints = false
view.wantsLayer = true
view.layer?.backgroundColor = CGColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Upvotes: 1
Views: 1012
Reputation: 1667
For changes to be animated, methods need to be called through the animator proxy. Making the change below gave the animations that I expected.
Incorrect:
collectionView.insertItems(at: [IndexPath(item: 0, section: 0)])
Correct:
collectionView.animator().insertItems(at: [IndexPath(item: 0, section: 0)])
This was not a concept that I was aware of before, and there is no mention of it in the collection view animation documentation.
Upvotes: 7