macOS 开发 - Drag & Drop 拖拽的基本使用


一、概述

如果应用中有对文本、文件、图片的移动、复制操作,Drag & Drop 是非常高效而直观的。


二、相关类与协议

Drag 相关类和协议位于 AppKit 中

  • NSDraggingImageComponent
  • NSDraggingItem
  • NSDraggingSession

protocols

  • NSDraggingInfo
  • NSDraggingDestination
  • NSDraggingSource
  • NSSpringLoadingDestination

  • 可拖拽的对象,需要遵守 NSDraggingSource 协议;

  • 可作为拖拽目标的对象,遵守 NSDraggingDestination 协议。

  • AppKit 隐藏了鼠标追踪和展示拖拽视图的所有细节。

  • NSWindow 和 NSView 对象可以成为drags 的资源地和目的地。


三、使用

让我们直接进入使用,上手后再进一步了解它吧,这里介绍一个简单的使用 NSView 作为接收端的样例吧。参考 demo:
https://github.com/huangqizai/Mac_DragDrop


1、构建视图

创建 OneView 继承自 NSView ;
在OneView 上添加一个 NSImageView 来获取拖拽的效果。


@interface OneView : NSView

@end


@interface OneView (){
    BOOL isReceivingDrag;  //是否正在拖拽操作
}
@property (nonatomic, strong) NSImageView *iconView;

@end


@implementation OneView

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    
    if (isReceivingDrag) {
        [[NSColor redColor] set];  //进入时,边框颜色变红
      
    }else{
        
        [[NSColor blueColor] set];  //正常状态下,边框颜色为蓝
    }
    
    NSBezierPath *path = [NSBezierPath bezierPathWithRect:dirtyRect];
    path.lineWidth = 2;
    [path stroke];
}



-(instancetype)initWithFrame:(NSRect)frameRect{
    
    self = [super initWithFrame:frameRect];
    
    self.wantsLayer = YES;
    self.layer.backgroundColor = [NSColor cyanColor].CGColor;
    
    self.iconView = [[NSImageView alloc]initWithFrame:NSMakeRect(5, 5, 470, 350)];
    [self addSubview:self.iconView];
    
    self.iconView.wantsLayer = YES;
    self.iconView.layer.backgroundColor = [NSColor yellowColor].CGColor;
    
    [self registerForDraggedTypes:@[NSPasteboardTypeFileURL, NSPasteboardTypePNG]];  // 注册拖拽类型
    
    return self;
}

点击 NSView 进入头文件,会发现它已经遵守 NSDraggingDestination 协议,所以这里我们不需要再次添加协议。


2、添加代理方法 NSDraggingDestination


#pragma mark - NSDraggingDestination

// 拖拽结束后调用(无论是否拖拽成功)
-(void)draggingEnded:(id<NSDraggingInfo>)sender{
    NSLog(@"-- draggingEnded");
    
    isReceivingDrag = NO;
    [self setNeedsDisplay:YES];
}


// 拖进来但没放下时调用
-(void)draggingExited:(id<NSDraggingInfo>)sender{
    NSLog(@"-- draggingExited");
    
}

/*
 拖动数据进入来时调用
 可以在这里判断数据是什么类型
*/
-(NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender{
    
    isReceivingDrag = YES;
    [self setNeedsDisplay:YES];
    
    NSPasteboard *pb = [sender draggingPasteboard];
    
    NSLog(@"-- draggingEntered \n pboard types : %@",[pb types]);

    if ([[pb types] containsObject:NSPasteboardTypeFileURL]) {
        return NSDragOperationCopy;
    }
    
    return NSDragOperationNone;
}

/*
 松开鼠标时会触发,可以在这里处理接收到的数据
*/
-(BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender{
    // 1)、获取拖动数据中的粘贴板
    NSPasteboard *pb = [sender draggingPasteboard];
    
    // 2)、从粘贴板中提取我们想要的NSFilenamesPboardType数据,这里获取到的是一个文件链接的数组,里面保存的是所有拖动进来的文件地址,如果你只想处理一个文件,那么只需要从数组中提取一个路径就可以了。
    NSArray *list = [pb propertyListForType:NSFilenamesPboardType];
    if (list.count > 0) {
        NSString *path = list.firstObject;
        self.iconView.image = [[NSImage alloc] initWithContentsOfFile:path];
    }
    
    
    NSLog(@"list : %@",list);
    
    return YES;
}

3、查看运行效果


应用运行起来的初始化效果
在这里插入图片描述


拖拽图片时(边框变红)
在这里插入图片描述


放下后
在这里插入图片描述


四、功能设计

关于功能的设计,最好阅读下面文档,来合理应用在不同场合。

https://developer.apple.com/design/human-interface-guidelines/macos/user-interaction/drag-and-drop/

在规划 Drag & Drop 功能的时候,最好也考虑一下几点:

  • 有其他替代的功能,能实现 Drag & Drop 同样的效果;
  • 让 Drag & Drop 操作可逆,以防止用户误操作;
  • Drag & Drop 可以产生移动或复制的效果。一般而言,在同一个应用、文档中(即使是不同的窗口),移动更有意义。在不同的应用、文档或磁盘之间,复制更有意义。

对于拖拽

  • 最好用户选中文件就可以拖拽到目的地。不要再这个过程中做选择、中断。
  • 允许用户从非激活窗口拖拽选中内容。a background selection。

五、参考

官方介绍


教程

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI工程仔

请我喝杯伯爵奶茶~!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值