1

我使用 .gesture 来拖动文本。

在此处输入图像描述

我想要发生的是剩余的字母向右移动,这样 'g' 占据第一个位置,剩余的字母向右移动。但我无法弄清楚我应该如何做到这一点。

struct TryingDrag: View {
    let letters = Array("Begin Saving")
    @State private var dragAmount = CGSize.zero
    
    var body: some View {
        HStack (spacing: 0) {
            ForEach(0..<letters.count) { index in
                let letter = String(letters[index])
                LettersDrag(letter: letter)
            }
        }
    }
}

struct LettersDrag: View {
    let letter: String
    @State private var dragAmount = CGSize.zero
    
    var body: some View {
        Text(letter).foregroundColor(.white)
            .padding(5)
            .font(.title)
            .background(Color.red)
            .offset(dragAmount)
            .animation(.spring())
            .gesture(
                DragGesture()
                    .onChanged {
                        dragAmount = $0.translation
                    }
                    
                    .onEnded { _ in
                        dragAmount = .zero
                    }
            )
    }
}

我希望它具有与下图类似的行为(但不使用列表/表单): 在此处输入图像描述

4

1 回答 1

3

您可以使用onDragonDrop实现它。我不得不稍微改变你的结构并添加一个模型来处理你的字母数据。

Asperi在这里很好地描述了拖放部分的工作原理。(这也是他的想法+代码,我只是针对您的情况进行了改编)

import SwiftUI
import UniformTypeIdentifiers

struct LettersData: Identifiable, Equatable {
    
    let id: Int
    let letter: String
}


class Model: ObservableObject {
    
    @Published var letters: [LettersData] = []

    
    init(input: String) {
        let inputArray = Array(input).map(String.init)
        
        for i in 0..<inputArray.count {
            letters.append(LettersData(id: i, letter: inputArray[i]))
        }
    }
}


struct TryingDrag: View {
    
    @StateObject private var model = Model(input: "Begin Saving")
    @State private var dragging: LettersData?
    
    
    var body: some View {
        HStack (spacing: 0) {
            ForEach(model.letters) { letter in
                LettersDrag(letter: letter.letter)
                    .onDrag {
                        self.dragging = letter
                        return NSItemProvider(object: String(letter.id) as NSString)
                    }
                    .onDrop(of: [UTType.text], delegate: DragRelocateDelegate(item: letter, listData: $model.letters, current: $dragging))
            }
        }
        .animation(.default, value: model.letters)
    }
}


struct LettersDrag: View {
    
    let letter: String
    
    
    var body: some View {
        Text(letter).foregroundColor(.white)
            .padding(5)
            .font(.title)
            .background(Color.red)
            .animation(.spring())
    }
}


struct DragRelocateDelegate: DropDelegate {
    
    let item: LettersData
    
    @Binding var listData: [LettersData]
    @Binding var current: LettersData?

    
    func dropEntered(info: DropInfo) {
        if item != current {
            let from = listData.firstIndex(of: current!)!
            let to = listData.firstIndex(of: item)!
            if listData[to].id != current!.id {
                listData.move(fromOffsets: IndexSet(integer: from),
                    toOffset: to > from ? to + 1 : to)
            }
        }
    }

    
    func dropUpdated(info: DropInfo) -> DropProposal? {
        return DropProposal(operation: .move)
    }

    
    func performDrop(info: DropInfo) -> Bool {
        self.current = nil
        return true
    }
}

我希望这就是你要找的。

于 2020-09-10T16:37:30.000 回答