OS X系统 Drag & Drop
来源:互联网 发布:好桌道类似软件 编辑:程序博客网 时间:2024/05/10 11:35
Drag & Drop(拖拽)提供了在应用与OS X系统,不同应用之间,应用内部多种场景下 资源,文件,数据可视化交换的极致的一种用户体验。
我们把可以拖拽的视图(view)或窗口(window)称为 拖放源(Drag Sources),接收拖放的视图或窗口称为 拖放目标(Drag Destination)。
拖放开始时会出现代表拖放源Drag Sources的图标顺着鼠标轨迹运动,直到拖放目标Drag Destination 接收了这个拖放请求,就完成了一次成功的拖放。如果拖放目标不能响应这个拖放请求,代表拖放源Drag Sources的图标会以动画形式弹回到拖放源以前的位置。
拖放源和拖放目标之间数据交换是通过使用系统的剪贴板(NSPasteboard)保存数据来完成的。
整个拖放过程中,涉及到拖放源和拖放目标之间一系列的交互处理流程。
拖放开始
用户鼠标点击NSView/NSWindow触发MouseDown事件,调用beginDraggingSessionWithItems方法开始建立一个拖放的session,开始启动拖放过程。
beginDraggingSessionWithItems需要3个参数,按顺序依次为拖放数据items,鼠标的NSEvent,拖放源代理。
(void)mouseDown:(NSEvent *)theEvent
{NSMutableArray *draggingItems = [NSMutableArray array];
NSPasteboardItem *pasteboardItem = [NSPasteboardItem new];
DragImageItem *dataProvider = [[DragImageItem alloc]init];
NSData *data = [self.image TIFFRepresentation];
dataProvider.data = data;
[pasteboardItem setDataProvider:dataProvider forTypes:@[kPasteboardTypeName]];
NSDraggingItem *draggingItem = [[NSDraggingItem alloc] initWithPasteboardWriter:pasteboardItem];
[draggingItems addObject:draggingItem];
[self beginDraggingSessionWithItems:draggingItems event:theEvent source:self.dragSourceDelegate];
}
拖放数据定义
拖放源跟拖放目标方约定数据的type类型,拖放源的数据按type类型存储,拖放接收方注册根据类型来获取数据。
NSPasteboardItem
使用NSPasteboardItem定义拖放携带的基本数据信息。NSPasteboardItem提供了3种基本的定义数据的方法和一个使用代理提供数据的方式。
1.基本的数据定义方法
可以定义NSData,NSString,id类型的数据
- (BOOL)setData:(NSData *)data forType:(NSString *)type;
- (BOOL)setString:(NSString *)string forType:(NSString *)type;
- (BOOL)setPropertyList:(id)propertyList forType:(NSString *)type;
2.使用代理方式提供数据
- (BOOL)setDataProvider:(id )dataProvider forTypes:(NSArray *)types;
实现代理类中定义获取数据的协议方法,实际上实现部分仍然是调用NSPasteboardItem的基本方法把数据存储起来。
(void)pasteboard:(nullable NSPasteboard *)pasteboard item:(NSPasteboardItem *)item provideDataForType:(NSString *)type;
{[item setData:self.data forType:type];
}
NSDraggingItem
使用NSDraggingItem包装NSPasteboardItem
NSDraggingItem *draggingItem = [[NSDraggingItem alloc] initWithPasteboardWriter:item];
拖放可视化定义
定义拖放过程中的跟随鼠标移动的图像。
draggingFrame中定义了拖放图像的位置,当有多个拖放对象一起拖放时,每个拖放图像的位置是不一样的。
imageComponentsProvider block块中定义了NSDraggingImageComponent对象, 可以在drawingHandler使用Cocoa绘图方法绘制出代表拖放的图像。block最后返回数据对象,方便表示多个不同的拖放源。
NSDraggingItem *draggingItem = [[NSDraggingItem alloc] initWithPasteboardWriter:pasteboardItem];
draggingItem.draggingFrame = NSMakeRect(0, 0, 16, 16);
draggingItem.imageComponentsProvider = {
NSDraggingImageComponent *component = [NSDraggingImageComponent draggingImageComponentWithKey:NSDraggingImageComponentIconKey];
component.frame = NSMakeRect(0, 0, 16, 16);
component.contents = [NSImage imageWithSize:NSMakeSize(16, 16) flipped:NO drawingHandler:NSRect rect {
NSImage *image = ....
[image drawInRect:rect];
return YES;
}];
return @[component];
};
拖放源协议NSDraggingSource
返回允许的拖放操作,代理必须实现的方法
- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context;
可选3个方法分别是拖放开始,拖放移动,拖放结束时的位置。
@optional
- (void)draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint;
- (void)draggingSession:(NSDraggingSession *)session movedToPoint:(NSPoint)screenPoint;
- (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation;
拖放内容
接收拖放
拖放接收方即拖放目标对象实现拖放目标方协议,通过协议的一系列方法依次调用,最终完成跟拖放源的数据交换,结束拖放。
注册接受的拖放类型
NSView 或 NSWindow 提供了注册拖放类型的方法registerForDraggedTypes
[self.window registerForDraggedTypes:[NSArray arrayWithObjects:
NSColorPboardType,
NSFilenamesPboardType,
NSURLPboardType,
NSFilesPromisePboardType
nil]];
可以使用Cocoa系统中预定义的类型,也可以自定义一种类型。
拖放目标方协议NSDraggingDestination
NSView 或 NSWindow 已经继承了NSDraggingDestination协议,需要拖放目标类来实现协议方法。
@protocol NSDraggingDestination
@optional
//拖放进入目标区
- (NSDragOperation)draggingEntered:(id )sender;
//拖放进入目标区移动
- (NSDragOperation)draggingUpdated:(id )sender;
//拖放退出目标区,拖放的图像会弹回到拖放源
- (void)draggingExited:(id )sender;
//拖放预处理,一般是根据拖放类型type,判断是否接受拖放。
- (BOOL)prepareForDragOperation:(id )sender;
//允许接收拖放,开始接收处理拖放数据
- (BOOL)performDragOperation:(id )sender;
//拖放完成结束
- (void)concludeDragOperation:(id )sender;
。。。
@end
拖放接收方处理过程
拖放源的代表图像进入拖放目标区,触发draggingEntered方法。draggingEntered中必须返回一种有效的拖放操作,如果返回NSDragOperationNone,接收拖放,拖放的图像会弹回到拖放源。
鼠标在拖放目标区移动,触发draggingUpdated。
鼠标退出目标区,调用draggingExited方法,拖放的图像会弹回到拖放源。
拖放源代表图像完全进入拖放目标区,释放鼠标按键。触发prepareForDragOperation方法,1. 如果返回NO,拖放的图像会弹回到拖放源,接收拖放。2. 如果返回YES,调用performDragOperation处理拖放,获取拖放数据,进行相关操作。最后调用concludeDragOperation完成一次成功的拖放。
拖放编程实践
前面的章节完整的阐述了拖放处理的全流程,实际应用中很多场景,不需要进行拖放源部分的编程,只需要进行拖放目标方的编程处理。
文件拖放处理
从OSX 系统Finder目录中拖放一个文件到应用。
自定义应用内部接收拖放的view视图类FileDragView,注册拖放类型,实现目标拖放协议NSDraggingDestination。
注册拖放类型
- (void)awakeFromNib {
[super awakeFromNib];[self registerForDraggedTypes:@[NSFilenamesPboardType]];
}
拖放文件进入拖放区,返回拖放操作类型
- (NSDragOperation)draggingEntered:(id )sender {
NSLog(@"drag operation entered");NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];NSPasteboard *pboard = [sender draggingPasteboard];if ( [[pboard types] containsObject:NSFilenamesPboardType] ) { if (sourceDragMask & NSDragOperationLink) { return NSDragOperationLink; } else if (sourceDragMask & NSDragOperationCopy) { return NSDragOperationCopy; }}return NSDragOperationNone;
}
执行拖放处理,获取文件路径。可以通过代理或通知形式发送消息通知Controller去处理。
- (BOOL)performDragOperation:(id )sender
{
NSPasteboard *pboard = [sender draggingPasteboard];
NSLog(@"drop now");if ( [[pboard types] containsObject:NSFilenamesPboardType] ) { NSArray *files = [pboard propertyListForType:NSFilenamesPboardType]; NSInteger numberOfFiles = [files count]; if(numberOfFiles>0) { NSString *filePath = [files objectAtIndex:0]; //if(self.delegate){ // [self.delegate didFinishDragWithFile:filePath]; //} return YES; }}else{ NSLog(@"pboard types(%@) not register!",[pboard types]);}return YES;
}
NSTableView的内部数据拖放处理
自定义NSTableView类DragTableView,在awakeFromNib方法中注册拖放类型为kDragTableViewTypeName.
实现NSTableViewDataSource协议,实现下面3个方法
1.数据复制到NSPasteboard
这里是将拖放时选择的的行rowIndexes 按kDragTableViewTypeName类型注册存储到系统剪贴板
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet )rowIndexes toPasteboard:(NSPasteboard)pboard {
// Copy the row numbers to the pasteboard.
NSData *zNSIndexSetData = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
[pboard declareTypes:[NSArray arrayWithObject:kDragTableViewTypeName] owner:self];
[pboard setData:zNSIndexSetData forType:kDragTableViewTypeName];
return YES;
}
- validate,返回允许的拖放操作类型
(NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id )info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)op {
//Add code here to validate the drop
//NSLog(@validate Drop
);
return NSDragOperationEvery;
}
3.拖放数据处理。
从剪贴板获取到rowIndexes,进行相关处理。
- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id )info
row:(NSInteger)row dropOperation:(NSTableViewDropOperation)operation {
NSPasteboard* pboard = [info draggingPasteboard];NSData* rowData = [pboard dataForType:kDragTableViewTypeName];NSIndexSet* rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:rowData];NSInteger dragRow = [rowIndexes firstIndex];return YES;
}
NSOutlineView的数据拖放处理
- 将拖放的节点数据 存储到剪切板
(BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard{
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:items];
[pboard declareTypes:[NSArray arrayWithObject:kDragOutlineViewTypeName] owner:self];
[pboard setData:data forType:kDragOutlineViewTypeName];
return YES;
}
2.validate,返回允许的拖放操作类型
- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id < NSDraggingInfo >)info proposedItem:(id)item proposedChildIndex:(NSInteger)index {
// Add code here to validate the drop
NSLog(@"validate Drop");return NSDragOperationEvery;
}
3.从剪贴板获取到拖放的数据items,进行相关处理。
- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id)info item:(id)item childIndex:(NSInteger)index {
NSPasteboard* pboard = [info draggingPasteboard];NSData* data = [pboard dataForType:kDragOutlineViewTypeName];NSArray* items = [NSKeyedUnarchiver unarchiveObjectWithData:data];....}
- OS X系统 Drag & Drop
- Drag &Drop
- Drag & Drop
- DRAG & DROP
- Drag Drop
- Drag and Drop
- 学习drag and drop
- Ole Drag & Drop
- drag与drop事件
- WebKit Drag & Drop
- 关于drag and drop
- Qt drag & drop
- Drag&Drop ListView
- drag,drop,datatransfer小结
- html5 Drag and drop
- Drag Drop行为探秘
- Drag & Drop (二)
- Drag & Drop (三)
- MAC OSX 沙盒机制
- opencv 如何输出某个pixel 的三维坐标
- 提高程序运行效率的10个简单方法
- 将C语言宏定义转换成字符串!
- XML中文显示问题
- OS X系统 Drag & Drop
- ajax 不进入回调函数 success
- 20160127.CCPP体系详解(0006天)
- hdu 5565 Clarke and baton
- 完全平方数
- 1.2.1 定义变量
- easyUI修饰的文本框绑定失去焦点事件
- UIButton设置图片不显示的问题
- 跳转到系统设置页(ios8及更高版本)