美文网首页
DragAndDropKit-iOS15下一行代码集成跨应用间拖

DragAndDropKit-iOS15下一行代码集成跨应用间拖

作者: JerryFans | 来源:发表于2022-01-19 11:36 被阅读0次

    前言

    前段时间苹果刚推出了iOS15正式版,我也是第一时间就升级了体验。期间体验到了一个非常有趣的交互如下视频。

    [图片上传失败...(image-6e15f5-1641800973359)]

    如视频所示,iOS15下的苹果系统相册支持将图片、视频,文本等直接拖拽复制到其他应用(目前亲测自带备忘录、腾讯QQ等是支持的)。作为一个iOS工程师,第一时间对此产生了浓厚的兴趣,第一时间查阅了官方文档,寻找实现方案,并以官方Api为基础,设计了DragAndDropKit,采用Swift编写,自带Drop、Drag命名空间,支持链式语法,原则上两行代码就可以让您项目支持拖拽资源分享到其他应用。

    支持版本

    原则上支持iPad OS 11 + , iPhone 是 iOS15+才支持。

    参考文档

    drag and drop

    下载地址

    cocoaPods:

    
    pod 'DragAndDropKit', '0.1.0'
    
    

    github:

    https://github.com/JerryFans/DragAndDropKit

    DragAndDropKit演示与用法

    [图片上传失败...(image-49125d-1641800973359)]

    Drag

    拖拽本应用的data到其他实现了Drop协议的应用(亲测支持系统相册、备忘录、网页里面的文本选中范围后直接拖拽等) DragAndDropKit本组件目前支持拖拽UIImage、本地视频(路径下的视频)、网络图片、网络视频、文本等。目前支持UIView及其类UIImageView、UILabel等、以及TableView、CollectionView快速拖动其子Cell。

    UIView Drag Usage

    最快只需两行代码即可实现拖拽,支持链式写法

    
    /*
                 你想拖拽时候给予的souce, 目前支持NetworkImageDropSource、NetworkVideoDropSource、ImageDropSource、VideoDropSource、TextDropSource五种
                 */
                self.networkImageView.drag.dropSource = NetworkImageDropSource(imageUrl: "http://image.jerryfans.com/sample.jpg")
                
                //开启拖拽
                self.networkImageView.drag.enabled()
    
    

    以及可选协议转链式闭包

    self.networkImageView.drag.enabled().didEndSession { interaction, session, operation in
                    
                }.didMoveSession { interaction, session in
                    
                }.didPreviewForDragSession { interaction, item, session in
                    return
                }.didAllowsMoveOperationSession { interaction, session in
                    return false
                }
    

    UICollectionView & UITableView Drag Usage

    UICollectionView、UITableView因为实习的协议不同,但本质写法是差不多的。
    两者enabled后都必须至少实现tableViewDidItemsForBeginning 或 collectionViewDidItemsForBeginning 闭包,返回相应的DragItem。DragItem封装的也是上面所说的5种DropSource。

    tableView

    
    tableView.drag.enabled().tableViewDidItemsForBeginning { [weak self] tableView, session, indexPath in
                    guard let self = self else { return [] }
                    //if you are the custom model, you should convert to DropSource Object (Text,Image or Video Drop Source)
                    let source = self.models[indexPath.row]
                    let itemProvider = NSItemProvider(object: source)
                    return [
                        UIDragItem(itemProvider: itemProvider)
                    ]
                }
    
    

    collectionView,如果要实现一些生命周期方法,可以实现一下生命周期闭包,同样是链式语法。

    collectionView.drag.enabled()
                .collectionViewDidItemsForBeginning { [weak self] collectionView, session, indexPath in
                    return self?.dragAndDropVM.dragItems(for: indexPath) ?? []
                }.collectionViewWillBeginDragSession { collectionView, session in
                    JFPopup.toast(hit: "collection view will begin drag")
                }.collectionViewDidEndDragSession { collectionView, session in
                    JFPopup.toast(hit: "collection view did end drag")
                }
    
    [图片上传失败...(image-cae300-1641800973359)] | image

    Drop

    从其他应用的接收data到到本应用(亲测支持系统相册、备忘录、QQ发送聊天等) DragAndDropKit本组件目前支持Drop 接收 UIImage、本地视频(路径下的视频)、网络图片、网络视频、文本等。目前也是支持UIView及其类UIImageView、UILabel等、以及TableView、CollectionView快速拖动其子Cell。

    Usage

    支持类型参数,所有UIView类别、TableView、CollectionView、均可赋值supportSources,用来声明drop接收时候能支持的类型数据,默认全部支持(Image、Video、Text)三种。(注:并不是系统api只支持这三种,是这三种比较广泛,第一期先支持此三种数据的接收)

    
    c.drop.supportSources = [.rawImage,.rawVideo,.text]
    
    

    UIView Drop, didReceivedDropSource闭包必须实现用以接收到source后你对source的处理,其他可选。

    
    self.view.drop.supportSources = [.rawImage]
                self.view.drop.enabled().didReceivedDropSource { [weak self] dropSources in
                    for (_, item) in dropSources.enumerated() {
                        if let imageSource = item as? ImageDropSource {
                            self?.imageView.image = imageSource.image
                            self?.imageView.layer.borderWidth = 0.0
                            break
                        }
                    }
                }.didEnterDropSession { interaction, session in
                    if session.localDragSession == nil {
                        JFPopupView.popup.toast {
                            [.hit("请移入右上角图片中替换"),
                             .withoutAnimation(true),
                             .position(.top),
                             .autoDismissDuration(.seconds(value: 3)),
                             .bgColor(UIColor.jf.rgb(0x000000, alpha: 0.3))
                            ]
                        }
                    }
                }.didUpdateDropSource { [weak self] interaction, session in
                    guard let self = self else {
                        return UIDropProposal(operation: UIDropOperation.cancel)
                    }
                    let dropLocation = session.location(in: self.view)
                    
                    let operation: UIDropOperation
                    
                    if self.imageView.frame.contains(dropLocation) {
                        operation = session.localDragSession == nil ? .copy : .move
                        self.checkIsMatch(match: true)
                    } else {
                        operation = .cancel
                        self.checkIsMatch(match: false)
                    }
                    self.updateLayers(forDropLocation: dropLocation)
                    
                    return UIDropProposal(operation: operation)
                }.didEndDropSession { [weak self] interaction, session in
                    guard let self = self else { return }
                    let dropLocation = session.location(in: self.view)
                    self.updateLayers(forDropLocation: dropLocation)
                    self.checkIsMatch(match: false)
                }.didExitDropSession { [weak self] interaction, session in
                    guard let self = self else { return }
                    self.imageView.layer.borderWidth = 0.0
                }
            }
    
    

    UICollectionView类似,也是collectionViewDidReceivedDropSource必须处理,其他生命周期闭包,可选。

    
    c.drop.supportSources = [.rawImage,.rawVideo,.text]
                c.drop.enabled().collectionViewDidReceivedDropSource { [weak self] collectionView, coordinator, dropSources in
                    let destinationIndexPath: IndexPath
                    
                    if let indexPath = coordinator.destinationIndexPath {
                        destinationIndexPath = indexPath
                    } else {
                        let item = collectionView.numberOfItems(inSection: 0)
                        destinationIndexPath = IndexPath(item: item, section: 0)
                    }
                    var indexPaths = [IndexPath]()
                    for (index, item) in dropSources.enumerated() {
                        let indexPath = IndexPath(item: destinationIndexPath.item + index, section: destinationIndexPath.section)
                        self?.dragAndDropVM.addItem(item, at: indexPath.item)
                        indexPaths.append(indexPath)
                    }
                    self?.collectionView.insertItems(at: indexPaths)
                }
    
    

    UITableView类似,也是tableViewDidReceivedDropSource必须处理,其他生命周期闭包,可选。

    
    t.drop.supportSources = [.rawImage,.rawVideo,.text]
                t.drop.enabled().tableViewDidReceivedDropSource { [weak self] tableView, coordinator, dropSources in
                    guard let self = self else { return }
                    
                    let destinationIndexPath: IndexPath
                    
                    if let indexPath = coordinator.destinationIndexPath {
                        destinationIndexPath = indexPath
                    } else {
                        let item = tableView.numberOfRows(inSection: 0)
                        destinationIndexPath = IndexPath(row: item, section: 0)
                    }
                    var indexPaths = [IndexPath]()
                    for (index, item) in dropSources.enumerated() {
                        let indexPath = IndexPath(row: destinationIndexPath.item + index, section: destinationIndexPath.section)
                        self.models.insert(item, at: indexPath.row)
                        indexPaths.append(indexPath)
                    }
                    tableView.insertRows(at: indexPaths, with: .bottom)
                }
    
    

    效果:

    [图片上传失败...(image-84abfd-1641800973359)]

    后续支持

    • tableView & collectionView 和系统相册一样支持多选拖拽支持(目前只能一个个拖cell)
    • 更多DropSource的支持

    相关文章

      网友评论

          本文标题:DragAndDropKit-iOS15下一行代码集成跨应用间拖

          本文链接:https://www.haomeiwen.com/subject/sywmcrtx.html