NSCollectionView Drag Drop示例

时间:2014-04-25 07:08:33

标签: macos cocoa

我正在尝试在NSCollectionView中实现拖放,这将允许在视图中重新排列单元格。我已设置委托并在以下方法中实现:

-(BOOL)collectionView:(NSCollectionView *)collectionView writeItemsAtIndexes:(NSIndexSet *)indexes toPasteboard:(NSPasteboard *)pasteboard {
    NSLog(@"Write Items at indexes : %@", indexes);
    return YES;
}

- (BOOL)collectionView:(NSCollectionView *)collectionView canDragItemsAtIndexes:(NSIndexSet *)indexes withEvent:(NSEvent *)event {
    NSLog(@"Can Drag");
    return YES;
}

- (BOOL)collectionView:(NSCollectionView *)collectionView acceptDrop:(id<NSDraggingInfo>)draggingInfo index:(NSInteger)index dropOperation:(NSCollectionViewDropOperation)dropOperation {
    NSLog(@"Accept Drop");
    return YES;
}

-(NSDragOperation)collectionView:(NSCollectionView *)collectionView validateDrop:(id<NSDraggingInfo>)draggingInfo proposedIndex:(NSInteger *)proposedDropIndex dropOperation:(NSCollectionViewDropOperation *)proposedDropOperation {
    NSLog(@"Validate Drop");
    return NSDragOperationMove;
}

我不确定如何进一步采取这一点。有了这个,我可以看到,现在我可以拖动个别收集项目,但我如何制作Drop

2 个答案:

答案 0 :(得分:6)

您只实现了委托方法,但某些方法中没有逻辑。例如,要拖动Collection Item,我将添加以下逻辑:

-(BOOL)collectionView:(NSCollectionView *)collectionView writeItemsAtIndexes:(NSIndexSet *)indexes toPasteboard:(NSPasteboard *)pasteboard {
    NSData *indexData = [NSKeyedArchiver archivedDataWithRootObject:indexes];
    [pasteboard setDraggedTypes:@["my_drag_type_id"]];
    [pasteboard setData:indexData forType"@"my_drag_type_id"];
    // Here we temporarily store the index of the Cell, 
    // being dragged to pasteboard.
    return YES;
}

- (BOOL)collectionView:(NSCollectionView *)collectionView acceptDrop:(id<NSDraggingInfo>)draggingInfo index:(NSInteger)index dropOperation:(NSCollectionViewDropOperation)dropOperation {
    NSPasteboard *pBoard = [draggingInfo draggingPasteboard];
    NSData *indexData = [pBoard dataForType:@"my_drag_type_id"];
    NSIndexSet *indexes = [NSKeyedUnarchiver unarchiveObjectWithData:indexData];
    NSInteger draggedCell = [indexes firstIndex];
    // Now we know the Original Index (draggedCell) and the 
    // index of destination (index). Simply swap them in the collection view array.
    return YES;
}

您还需要注册集合视图以在awakefromnib中拖动类型

[_myCollectionView registerForDraggedTypes:@[KL_DRAG_TYPE]];

并确保您已将集合视图设置为可选。

答案 1 :(得分:1)

除了上面提到的GoodSp33d之外,你还缺少接受删除所需的validate委托功能。在Swift中,这是:

func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer<NSIndexPath>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionViewDropOperation>) -> NSDragOperation

请注意返回值NSDragOperation。此方法应包含准确确定正在尝试的拖动操作类型的代码并返回此值。返回错误的东西会导致一些非常恼人的错误。

进一步注意,为了支持这种操作,您使用的集合视图布局类还必须支持拖放。流布局应该是开箱即用的,但是如果您使用自定义布局,则可能需要对其进行调整以支持拖放,以便集合视图可以检测有效的放置目标并确定合适的索引他们的道路。