You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在拖拽NSCollectionView项时实现交互式重排?

NSCollectionView实现拖拽时交互式移开现有项的方法

像Preview这类应用会在拖拽操作时通过交互式地移开现有项来指示放置位置,效果为拖拽过程中周围的项自动腾出空间以展示放置位置。

据我回忆(IIRC),这也是所有标准布局下UICollectionView的默认行为。相比之下,NSCollectionView仅会显示插入指示器,不会重新排列项,我始终无法找到实现上述效果的方法。有趣的是,另一篇问题的截图显示了我想要的效果,但讨论内容并不相关。

当前拖拽代理设置代码

- (BOOL)collectionView:(NSCollectionView *)collectionView canDragItemsAtIndexPaths:(NSSet<NSIndexPath *> *)indexPaths withEvent:(NSEvent *)event {
    return YES;
}

- (id<NSPasteboardWriting>)collectionView:(NSCollectionView *)collectionView pasteboardWriterForItemAtIndexPath:(NSIndexPath *)indexPath {
    NSPasteboardItem *pasteboardItem = [[NSPasteboardItem alloc] init];
    [pasteboardItem setString:@"Whatever is fine" forType:NSPasteboardTypeString];
    
    return pasteboardItem;
}

- (NSDragOperation)collectionView:(NSCollectionView *)collectionView validateDrop:(id<NSDraggingInfo>)draggingInfo proposedIndexPath:(NSIndexPath * _Nonnull __autoreleasing *)proposedDropIndexPath dropOperation:(NSCollectionViewDropOperation *)proposedDropOperation {
    *proposedDropOperation = NSCollectionViewDropBefore;
    
    return NSDragOperationMove;
}

我原本以为布局的-layoutAttributesForDropTargetAtPoint:/-layoutAttributesForInterItemGapBeforeIndexPath:方法是用于实现该效果的,但实际上它们仅用于设置指示器位置,不会影响项的排列。

例如在子类化的NSCollectionViewFlowLayout中设置任意矩形:

- (NSCollectionViewLayoutAttributes *)layoutAttributesForDropTargetAtPoint:(NSPoint)pointInCollectionView {
    NSCollectionViewLayoutAttributes *attributes = [[super layoutAttributesForDropTargetAtPoint:pointInCollectionView] copy];
    attributes.frame = NSMakeRect(60, 0, 200, 200);

    return attributes;
}

这段代码只会将指示器渲染在{60, 0}位置,但不会对项的排列产生任何影响。

我当然可以进一步扩展布局使其感知拖拽会话,但这感觉像是一种取巧方案;而且在拖拽期间手动使布局失效(更不用说通过-performBatchUpdates:completionHandler:触发动画响应),无疑印证了这一点。另一种方法是直接操作项的frame,但这也像是在与NSCollectionView的设计逻辑对抗,而非利用其特性。

鉴于这种交互模式应用广泛,肯定存在无需取巧的正确实现方式。我忽略了什么?谢谢。


内容的提问来源于stack exchange,提问作者K Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 02:05:33