NSCollectionView - dragging shows a hole - want it to look lke the Finder
This appears to be essentially the same question as Prevent NSCollectionView 'lifting' an item during drag
My initial solution was to use a custom view for the collection view item. In my subclass I override setHidden:
to prevent the collection view from hiding my item view while the item is being dragged. This had some undesirable side-effects. It appears that NSCollectionView also hides item views when changing the layout.
The next idea (so far) works fine in my application. I un-hide the item views when dragging starts.
@interface HGImagesCollectionViewDelegate : NSObject <NSCollectionViewDelegate>
@end
@implementation HGImagesCollectionViewDelegate
- (void)collectionView:(NSCollectionView *)collectionView
draggingSession:(NSDraggingSession *)session
willBeginAtPoint:(NSPoint)screenPoint
forItemsAtIndexPaths:(NSSet<NSIndexPath *> *)indexPaths
{
// Prevent item from being hidden (creating a hole in the grid) while being dragged
for (NSIndexPath *indexPath in indexPaths) {
[[[collectionView itemAtIndexPath:indexPath] view] setHidden:NO];
}
// …
}
@end
NSCollectionView: Accept Drag Only Between Items, not Over
So, after some more research, I found that the validadeDrop
method has
a parameter that describes exactly that, if the operation is over or in
between. And since it is given as a reference, one can change the
parameter to overwrite a certain behaviour. So, the solution is to add
this check to the method:
- (NSDragOperation)
collectionView:(NSCollectionView *)collectionView
validateDrop:(id<NSDraggingInfo>)draggingInfo
proposedIndex:(NSInteger *)proposedDropIndex
dropOperation:(NSCollectionViewDropOperation *)proposedDropOperation
{
/* ... */
if (*proposedDropOperation == NSCollectionViewDropOn)
*proposedDropOperation = NSCollectionViewDropBefore;
/* ... */
}
Drag selecting in NSCollectionView from inside of items
Implement hitTest(_:)
in the class of the item view to make the items "see through" for clicks. Return the collection view instead of the item view when the user clicks in the item view.
override func hitTest(_ point: NSPoint) -> NSView? {
var view = super.hitTest(point)
if view == self {
repeat {
view = view!.superview
} while view != nil && !(view is NSCollectionView)
}
return view;
}
OS X: How to pass mouse drag events through a view to superview
You can use the function on NSView
func unregisterDraggedTypes()
on the NSImageView
that you create to stop them from eating up the images on the pasteboard.
That should allow the underlying NSTabView
subclass to receive the drag events.
Alternatively if thats not working, place a NSView
subclass which will receive the drag events over the top of the NSTabview
and override the hitTest
so clicks get through to the views underneath.
override func hitTest(aPoint: NSPoint) -> NSView? {
return nil
}
Alternative to NSCollectionView in pre-OSX10.5, Cocotron?
To work with NSCollectionView, you need to not only understand KVC and KVO, but also Bindings.
There's code for an NSCollectionView clone that works on Tiger here.
Related Topics
Cloudkit - What to Do When a User Adds, Modifies or Deletes an Object While Offline
Adding Data to a Specific UId in Firebase
Create Skspritenode with an Asset Programmatically
How to Download Datas from Multiple Url in Concurrency Mode
Swift-Making an Sknode Simply "Move Forward" on an Angle
Closure (With Default Value) as Function Parameter
Swift 4, Simultaneous Access to Tuple Members as Inout
Uicollectionview Selected Cells Issue
Dynamic UIcollectionviewcell Width with Respect to Frame Width and Aspect Ratio
Can Not Import Tensorflow for Swift in Xcode Playground
Cannot Assign Value of Type 'Menuview' to Type 'some View'
How to Drag a Working Slider Using Swiftui
Pass Data from Tableviewcontroller to Another Tableviewcontroller in Swift
Spritekit: Sprites Are Moving Through Each Other with a Physicsbody Already Set
Watchkit Extension Cannot Read from Icloud