我有一个简单的、单列的、基于 View 的 NSTableView,其中包含可以拖动以重新排序的项目。在拖放过程中,我想让它在鼠标下方的位置打开要放置的项目的间隙。当您拖动以重新排序轨道时,GarageBand 会执行类似的操作(此处的视频:http://www.screencast.com/t/OmUVHcCNSl)。据我所知,NSTableView 中没有对此的内置支持。
有没有其他人尝试将此行为添加到 NSTableView 并找到了一个好的解决方案?我已经想到并尝试了几种方法但没有太大成功。我的第一个想法是通过在我的数据源的 -tableView:validateDrop:...
方法中发送 -noteHeightOfRowsWithIndexesChanged:
来在拖动过程中将鼠标下方行的高度加倍,然后在 -tableView:heightOfRow:
中返回正常高度的两倍。不幸的是,据我所知,NSTableView 在拖放期间不会更新其布局,因此尽管调用了 noteHeightOfRowsWithIndexesChanged:
,行高实际上并未更新。
请注意,我使用的是基于 View 的 NSTableView,但我的行并没有复杂到我无法移动到基于单元格的 TableView (如果这样做有助于实现此目的)。我知道在拖动完成后为放置的项目制作间隙动画的简单内置功能。我正在寻找一种在拖动过程中打开间隙的方法。此外,这是针对要在 Mac App Store 中销售的应用程序,因此它不得使用私有(private) API。
编辑:我刚刚向 Apple 提交了增强请求,请求内置支持此行为:http://openradar.appspot.com/12662624 . 如果你也想看到它,请上当。 更新:我要求的增强功能已在 OS X 10.9 Mavericks 中实现,现在可以使用 NSTableView API 实现此行为。参见 NSTableViewDraggingDestinationFeedbackStyleGap .
最佳答案
我觉得这样做很奇怪,但是这里的队列中有一个非常详尽的答案,似乎已被其作者删除。在其中,他们提供了the correct links to a working solution ,我觉得需要将其作为答案呈现给其他人接受和使用,如果他们愿意的话也包括在内。
来自 NSTableView
的文档, 以下注意事项隐藏在行动画效果中:
Row Animation Effects
Optional constant that specifies that the tableview will use a fade for row or column removal. The effect can be combined with any
NSTableViewAnimationOptions
constant.enum { NSTableViewAnimationEffectFade = 0x1, NSTableViewAnimationEffectGap = 0x2, };
Constants:
...
NSTableViewAnimationEffectGap
Creates a gap for newly inserted rows. This is useful for drag and drop animations that animate to a newly opened gap and should be used in the delegate method
tableView:acceptDrop:row:dropOperation:
.
通过 the example code from Apple ,我发现这个:
- (void)_performInsertWithDragInfo:(id <NSDraggingInfo>)info parentNode:(NSTreeNode *)parentNode childIndex:(NSInteger)childIndex {
// NSOutlineView's root is nil
id outlineParentItem = parentNode == _rootTreeNode ? nil : parentNode;
NSMutableArray *childNodeArray = [parentNode mutableChildNodes];
NSInteger outlineColumnIndex = [[_outlineView tableColumns] indexOfObject:[_outlineView outlineTableColumn]];
// Enumerate all items dropped on us and create new model objects for them
NSArray *classes = [NSArray arrayWithObject:[SimpleNodeData class]];
__block NSInteger insertionIndex = childIndex;
[info enumerateDraggingItemsWithOptions:0 forView:_outlineView classes:classes searchOptions:nil usingBlock:^(NSDraggingItem *draggingItem, NSInteger index, BOOL *stop) {
SimpleNodeData *newNodeData = (SimpleNodeData *)draggingItem.item;
// Wrap the model object in a tree node
NSTreeNode *treeNode = [NSTreeNode treeNodeWithRepresentedObject:newNodeData];
// Add it to the model
[childNodeArray insertObject:treeNode atIndex:insertionIndex];
[_outlineView insertItemsAtIndexes:[NSIndexSet indexSetWithIndex:insertionIndex] inParent:outlineParentItem withAnimation:NSTableViewAnimationEffectGap];
// Update the final frame of the dragging item
NSInteger row = [_outlineView rowForItem:treeNode];
draggingItem.draggingFrame = [_outlineView frameOfCellAtColumn:outlineColumnIndex row:row];
// Insert all children one after another
insertionIndex++;
}];
}
我不确定它是否真的这么简单,但如果它不能满足您的需求,它至少值得检查和彻底反驳。
编辑:查看此答案的评论以了解正确解决方案所遵循的步骤。 OP 已发布 a more complete answer ,任何寻找相同问题解决方案的人都应该引用。
关于objective-c - 在拖放过程中在 NSTableView 中打开一个缺口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10142675/