美文网首页
SwiftUI拖动变换位置

SwiftUI拖动变换位置

作者: xo1988 | 来源:发表于2022-08-22 22:29 被阅读0次

实现一下SwiftUI拖动变化位置的功能。
涉及到的是使用 onDrag 和 onDrop 属性。
大体的思路就是在 onDrag 中记录下移动中的元素, 在 onDrop 中根据移动到的位置改变移动元素插入的位置。
有两个版本效果。

1. 首先简单版本效果。

drop.gif

代码如下:

import SwiftUI

struct Test: View {
    @State private var targeted = true
    @State private var tags = [0,1,2,3,4,5,6,7,8,9,10]
    
    var body: some View {
        let adaColumns = [
            GridItem(.adaptive(minimum: 60, maximum: 80))]
        
        VStack {
            LazyVGrid(columns: adaColumns) {
                ForEach(tags, id: \.self) { tag in
                    Text("\(tag)")
                        .font(.subheadline)
                        .padding(.vertical, 8)
                        .frame(maxWidth: .infinity)
                        .background(
                            Color.init(hexString: "#dddddd")
                        )
                        .cornerRadius(4)
                        .onDrag {
                            let item = NSItemProvider(object: NSString(string: "\(tag)"))
                            item.suggestedName = "\(tag)"
                            return item
                        }
                        .onDrop(of: [.text], isTargeted: $targeted) { providers in
                            print("drop \(providers.first) \(tag)")
                            guard let provider = providers.first, let item = provider.suggestedName else {
                                return false
                            }
                            let a = Int(item)
                            let i = tags.firstIndex(of: a!)
                            withAnimation {
                                tags.remove(at: I!)
                                let j = tags.firstIndex(of: tag)
                                tags.insert(a!, at: j!)
                            }
                            return true
                        }
                }
            }
            .frame(maxWidth: .infinity)
        }
        .padding()
    }
}

struct Test_Previews: PreviewProvider {
    static var previews: some View {
        Test()
    }
}

改进版效果

使用到了 DropDelegate 协议,能够获取移动中和碰撞的两个元素的事件,能够在运动中进行控制,方便实现更完美的动画。


update.gif
import SwiftUI
import UniformTypeIdentifiers

final class TModel: NSObject {
    var id: UUID
    var tag: String
    
    internal init(id: UUID, tag: String) {
        self.id = id
        self.tag = tag
    }
}

enum MoveEnum: Int {
    case left
    case right
}

struct DragRelocateDelegate: DropDelegate {
    let item: TModel
    var listData: [TModel]
    @Binding var current: TModel?
    
    var moveAction: (MoveEnum) -> Void
    
    func dropEntered(info: DropInfo) {
    }
    
    func dropUpdated(info: DropInfo) -> DropProposal? {
        print("update location.x is \(info.location.x)")
        if item != current {
            if info.location.x > 30 {
                moveAction(.right)
            } else {
                moveAction(.left)
            }
        }

        return DropProposal(operation: .move)
    }
    
    func performDrop(info: DropInfo) -> Bool {
        return true
    }
}

struct Test1: View {
    @State private var targeted = true
    @State private var tags:[TModel]
    @State var dragTag: TModel?

    init() {
        var __tags:[TModel] = []
        for i in 0...10 {
            __tags.append(TModel.init(id: UUID(), tag: "\(i)"))
        }
        _tags = State.init(initialValue: __tags)
    }
    
    var body: some View {
        
        let adaColumns = [
            GridItem(.adaptive(minimum: 60, maximum: 80))]
        
        VStack {
            LazyVGrid(columns: adaColumns) {
                ForEach(tags, id: \.id) { item in
                    Text(item.tag)
                        .font(.subheadline)
                        .padding(.vertical, 8)
                        .frame(maxWidth: .infinity)
                        .background(
                            Color.init(hexString: "#dddddd")
                        )
                        .cornerRadius(4)
                        .onDrag {
                            let provider = NSItemProvider(object: NSString(string: item.id.uuidString))
                            provider.suggestedName = "tags"
                            
                            dragTag = item
                            return provider
                        }
                        .onDrop(of: [.text], delegate: DragRelocateDelegate(item: item, listData: tags, current: $dragTag, moveAction: { direction in
                            if item == dragTag {
                                return
                            }
                            
                            let i = tags.firstIndex(of: dragTag!)
                            withAnimation {
                                tags.remove(at: I!)
                                let j = tags.firstIndex(of: item)
                                if direction == .left {
                                    tags.insert(dragTag!, at: j!)
                                } else {
                                    tags.insert(dragTag!, at: j! + 1)
                                }
                            }
                        }))
                }
            }
            .frame(maxWidth: .infinity)
        }
        .padding()
    }
}

struct Test1_Previews: PreviewProvider {
    static var previews: some View {
        Test1()
    }
}

相关文章

  • SwiftUI拖动变换位置

    实现一下SwiftUI拖动变化位置的功能。涉及到的是使用 onDrag 和 onDrop 属性。大体的思路就是在 ...

  • SwiftUI List编辑,拖动、删除、横滑

    研究了一下SwiftUI的List。使用自带的编辑模式能简便的实现很多功能。主要涉及: onDrag onMove...

  • SwiftUI—如何给视图添加拖动手势

    原文链接:https://github.com/fzhlee/SwiftUI-Guide#-%E7%AC%AC5%...

  • Redux For SwiftUI

    摘自《SwiftUI和Combine编程》---《SwiftUI架构》 Redux For SwiftUI 架构图...

  • UITableView 拖拽移动单元格

    小萌做开发的时候,项目需求是:拖拽单元格随意变换位置,变换位置之后仍然可以编辑其它,界面需求如下图所示。 小萌在网...

  • SwiftUI 实现微博项目

    WeiBo-SwiftUI 微博App项目实战 仓库代码:appke/WeiBo-SwiftUI: SwiftUI...

  • js的拖动相关

    拖动相关的事件 dragstart: 被拖动元素 开始拖动 时触发的事件。 drag: 被拖动元素 拖动过程 触发...

  • HTML笔记16:HTML5拖放

    拖动事件 拖动实例 拖动元素添加属性 拖动我! 定义拖动ondragstart 设置目标释放后,放置的位置ondr...

  • SwiftUI02

    SwiftUI Essentials SwiftUI要点 Creating and Combining Views...

  • SwiftUI01

    .Introducing SwiftUI SwiftUI is a modern way to declare u...

网友评论

      本文标题:SwiftUI拖动变换位置

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